home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1996-04-03 | 131.2 KB | 4,343 lines | [ TEXT/MPS ]
//---------------------------------------------------------------------------------------- // UDispatcher.cp // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved. //---------------------------------------------------------------------------------------- #ifndef __UDISPATCHER__ #include "UDispatcher.h" #endif // MacApp #ifndef __UBEHAVIOR__ #include "UBehavior.h" #endif #ifndef __UBUSYCURSOR__ #include "UBusyCursor.h" #endif #ifndef __UCLIPBOARDMGR__ #include "UClipboardMgr.h" #endif #if qContainer #ifndef __UCONTAINER__ #include "UContainer.h" #endif #endif #ifndef __UCOREERRORMGR__ #include "UCoreErrorMgr.h" #endif #ifndef __UCOREGLOBALS__ #include "UCoreGlobals.h" #endif #ifndef __UCOREUTILITIES__ #include "UCoreUtilities.h" #endif #ifndef __UDEBUG__ #include "UDebug.h" #endif #ifndef __UDEPENDENCIES__ #include "UDependencies.h" #endif #ifndef __UDESIGNATOR__ #include "UDesignator.h" #endif #ifndef __UDOCUMENT__ #include "UDocument.h" #endif #ifndef __UERRORMGR__ #include "UErrorMgr.h" #endif #ifndef __UFILE__ #include "UFile.h" #endif #if qContainer #ifndef __UFILEBASEDDOCUMENT__ #include "UFileBasedDocument.h" #endif #ifndef __UODPARTVIEW__ #include "UODPartView.h" #endif #endif #ifndef __FLOATWINDOW__ #include "FloatWindow.h" #endif #ifndef __UGEOMETRY__ #include "UGeometry.h" #endif #ifndef __UMACAPPGLOBALS__ #include "UMacAppGlobals.h" #endif #ifndef __UMACAPPUTILITIES__ #include "UMacAppUtilities.h" #endif #ifndef __UMEMORY__ #include "UMemory.h" #endif #ifndef __UMENUMGR__ #include "UMenuMgr.h" #endif #ifndef __UPATCH__ #include "UPatch.h" #endif #ifndef __UPRINTHANDLER__ #include "UPrintHandler.h" #endif #ifndef __UOSASCRIPT__ #include "UOSAScript.h" #endif #ifndef __USCRIPTING__ #include "UScripting.h" #endif #ifndef __USEGMENTS__ #include "USegments.h" #endif #ifndef __USTREAM__ #include "UStream.h" #endif #ifndef __UTRACKER__ #include "UTracker.h" #endif #ifndef __UUNDO__ #include "UUndo.h" #endif #ifndef __UVIEWSERVER__ #include "UViewServer.h" #endif #ifndef __UWINDOW__ #include "UWindow.h" #endif // CALib #if qContainer #ifndef _CALIB_ #include "CALib.h" #endif #endif // Toolbox #ifndef __AEREGISTRY__ #include <AERegistry.h> #endif #ifndef __DEVICES__ #include <Devices.h> #endif #ifndef __DISKINIT__ #include <DiskInit.h> #endif #ifndef __ERRORS__ #include <Errors.h> #endif #ifndef __LOWMEM__ #include <LowMem.h> #endif #ifndef __RESOURCES__ #include <Resources.h> #endif #ifndef __TOOLUTILS__ #include <ToolUtils.h> #endif // ANSI #ifndef __STDIO__ #include <stdio.h> #endif // Other #if defined(__MWERKS__) && (qDebug || qTheDebugger) #ifndef __CWDEBUG__ #include "CWDebug.h" #endif #endif //---------------------------------------------------------------------------------------- // Constant definitions //---------------------------------------------------------------------------------------- enum SystemJustification { smSysJustLeft = 0, smSysJustRight = -1 }; // Constants to use with GetSysDirection() and SetSysDirection(). //---------------------------------------------------------------------------------------- // Global variable definitions. //---------------------------------------------------------------------------------------- TDispatcher* gDispatcher; Boolean gInitialized; AEAddressDesc gServerAddress; Boolean gHasODFocus; Boolean gHasODModalFocus; // Boolean hadCreditsStringList; // does the rsrc 'STR#' == kDefaultCredits exist ? // short lastCreditsStringIndex; // the last CString in the STR# to be displayed // long lastCreditsShownTicks; // the tickcount when the last Credit was Shown // CStringHandle originalText; // the about box's original text (prior to credits) // short waitTicks; // how long to wait between credits //======================================================================================== // GLOBAL Procedures //======================================================================================== static void DoSetupTheMenus(void* yourDataPtr); static WindowRef GetWindowToClose(); #undef Inherited //======================================================================================== // CLASS CEventListIterator //======================================================================================== #undef Inherited #pragma segment MAApplicationRes class CEventListIterator { public: inline CEventListIterator(const TEventList* itsEventList) : fCurrentIndex(itsEventList->GetSize()), // We iterate backward over the event list fEventList(itsEventList) { } inline Boolean More() { return (fCurrentIndex != kEmptyIndex); } // Returns true if there are more elements to iterate over inline TEvent* FirstEvent() { return this->More() ? (TEvent*)fEventList->At(fCurrentIndex) : NULL; } // Resets the iterator to begin again and returns the value of the first index in // the iteration inline TEvent* NextEvent() { this->Advance(); return this->More() ? (TEvent*)fEventList->At(fCurrentIndex) : NULL; } // Advances the iteration and then returns the index protected: inline void Advance() { fCurrentIndex = (fCurrentIndex > 1) ? fCurrentIndex - 1 : kEmptyIndex; } // Advances the iteration public: // These items are currently public for searching ArrayIndex fCurrentIndex; // current index of this iteration protected: const TEventList* fEventList; // the main event list }; //======================================================================================== // CLASS CDocumentIterator //======================================================================================== #undef Inherited //---------------------------------------------------------------------------------------- // CDocumentIterator::CDocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CDocumentIterator::CDocumentIterator(const TDispatcher* itsApplication, ArrayIndex itsLowBound, ArrayIndex itsHighBound, Boolean itsForward) : CObjectIterator(itsApplication ? itsApplication->fDocumentList : NULL, itsLowBound, itsHighBound, itsForward) { } // CDocumentIterator::CDocumentIterator //---------------------------------------------------------------------------------------- // CDocumentIterator::CDocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CDocumentIterator::CDocumentIterator(const TDispatcher* itsApplication, Boolean itsForward) : CObjectIterator(itsApplication ? itsApplication->fDocumentList : NULL, itsForward) { } // CDocumentIterator::CDocumentIterator //---------------------------------------------------------------------------------------- // CDocumentIterator::CDocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CDocumentIterator::CDocumentIterator(const TDispatcher* itsApplication) : CObjectIterator(itsApplication ? itsApplication->fDocumentList : NULL, kIterateForward) { } // CDocumentIterator::CDocumentIterator //---------------------------------------------------------------------------------------- // CDocumentIterator::~CDocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment IteratorRes CDocumentIterator::~CDocumentIterator() { } // CDocumentIterator::~CDocumentIterator #if qContainer //======================================================================================== // CLASS CCADocumentIterator //======================================================================================== //---------------------------------------------------------------------------------------- // CCADocumentIterator::CCADocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CCADocumentIterator::CCADocumentIterator(const TDispatcher* itsApplication, ArrayIndex itsLowBound, ArrayIndex itsHighBound, Boolean itsForward) : CObjectIterator(itsApplication ? itsApplication->fCADocumentList : NULL, itsLowBound, itsHighBound, itsForward) { } // CCADocumentIterator::CCADocumentIterator //---------------------------------------------------------------------------------------- // CDocumentIterator::CCADocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CCADocumentIterator::CCADocumentIterator(const TDispatcher* itsApplication, Boolean itsForward) : CObjectIterator(itsApplication ? itsApplication->fCADocumentList : NULL, itsForward) { } // CCADocumentIterator::CCADocumentIterator //---------------------------------------------------------------------------------------- // CCADocumentIterator::CCADocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CCADocumentIterator::CCADocumentIterator(const TDispatcher* itsApplication) : CObjectIterator(itsApplication ? itsApplication->fCADocumentList : NULL, kIterateForward) { } // CCADocumentIterator::CCADocumentIterator //---------------------------------------------------------------------------------------- // CCADocumentIterator::~CCADocumentIterator: //---------------------------------------------------------------------------------------- #pragma segment IteratorRes CCADocumentIterator::~CCADocumentIterator() { } // CCADocumentIterator::~CCADocumentIterator #endif //======================================================================================== // CLASS CNoGhostDocsIterator //======================================================================================== #undef Inherited //---------------------------------------------------------------------------------------- // CNoGhostDocsIterator::~CNoGhostDocsIterator: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CNoGhostDocsIterator::~CNoGhostDocsIterator() { } //---------------------------------------------------------------------------------------- // CNoGhostDocsIterator::More: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean CNoGhostDocsIterator::More() { Boolean more = FALSE; // advances iterator to next valid document while (!more && CDocumentIterator::More()) { if (!((TDocument*)((TSortedList*)fDynamicArray)->At(fCurrentIndex))->GetIsGhostDocument()) more = TRUE; else this->Advance(); } return more; } //======================================================================================== // struct CSetupTheMenus //======================================================================================== struct CSetupTheMenus { public: TDispatcher* fDispatcher; // Constructor inline CSetupTheMenus(TDispatcher* theDispatcher) : fDispatcher(theDispatcher) { } }; //---------------------------------------------------------------------------------------- // DoSetupTheMenus: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void DoSetupTheMenus(void* /* yourDataPtr */) { #if qContainer if (gContainerLib) { CAAdjustMenus(); OSErr theErr = CAError(); if (theErr != noErr) ; // handle the error } #endif if (!gDispatcher) return; // Set the Undo and Redo menu items // // to "Can't Undo" before giving the target chain a chance // // to change it. // gDispatcher->SetUndoText(cCantUndo); // gDispatcher->SetRedoText(cCantUndo); gDispatcher->SetupUndoRedoMenus(); gClipboardMgr->fGotClipType = FALSE; // so CanPaste will work correctly gDispatcher->GetTarget()->HandleSetupMenus();// Setup menus relevant to target chain // Set up the menu commands that are not dependent on the target chain… if (gDispatcher->fSysWindowActive) { Enable(cUndo, TRUE); Enable(cCut, TRUE); Enable(cCopy, TRUE); Enable(cPaste, TRUE); Enable(cClear, TRUE); gDispatcher->SetUndoText(cNoCommand); gDispatcher->SetRedoText(cNoCommand); } #if qPerform { Boolean initiated = PerfMonitorInitiated(); Enable(cPerfMonInit, !initiated); Enable(cPerfMonDump, initiated); Enable(cPerfMonToggle, initiated); SetMenuState(cPerfMonToggle, kDebugBuzzStrings, bzContinuePerfMon, bzPausePerfMon, PerfMonitorEnabled()); Enable(cPerfMonEnd, initiated); } #endif Enable(cAboutApp, TRUE); Enable(-(mApple << 8), TRUE); if (CommandEnabled(cAboutApp) && gDispatcher->InModalState()) { WindowRef aWindowPtr = FrontWindow(); if (aWindowPtr && GetWindowVariant(aWindowPtr) == movableDBoxProc) Enable(cAboutApp, FALSE); // just disallow the about item else Enable(-(mApple << 8), FALSE); // disallow the whole menu } } // DoSetupTheMenus //======================================================================================== // CLASS TEventList: Empty constructor to satisfy the compiler. //======================================================================================== #undef Inherited #define Inherited TSortedList #pragma segment MAInit MA_DEFINE_CLASS_M1(TEventList, Inherited); //---------------------------------------------------------------------------------------- // TEventList::TEventList: Empty constructor to satisfy the compiler. //---------------------------------------------------------------------------------------- #pragma segment ConstructorRes TEventList::TEventList() { } // TEventList::TEventList //---------------------------------------------------------------------------------------- // TEventList destructor //---------------------------------------------------------------------------------------- #pragma segment MADestructorRes TEventList::~TEventList() { } //---------------------------------------------------------------------------------------- // TEventList::Compare: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes CompareResult TEventList::Compare(TObject* item1, TObject* item2) { CompareResult returnVal = kItem1EqualItem2; // We want higher priority events at the end of the queue so we can delete from the // end of the list. This will save us a block move in DeleteElementsAt. if (((TEvent *)item1)->fPriority > ((TEvent *)item2)->fPriority) returnVal = kItem1LessThanItem2; else if (((TEvent *)item1)->fPriority < ((TEvent *)item2)->fPriority) returnVal = kItem1GreaterThanItem2; return returnVal; } // TEventList::Compare //---------------------------------------------------------------------------------------- // TEventList::IEventList: //---------------------------------------------------------------------------------------- #pragma segment MAInit void TEventList::IEventList() { this->ISortedList(); } // TEventList::IEventList //---------------------------------------------------------------------------------------- // TEventList::Insert: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TEventList::Insert(TObject* item) // override { MAVolatileInit(Boolean, oldObjectPerm, AllocateObjectsFromPerm(FALSE)); FailInfo fi; Try(fi) { Inherited::Insert(item); fi.Success(); } else { AllocateObjectsFromPerm(oldObjectPerm); fi.ReSignal(); } AllocateObjectsFromPerm(oldObjectPerm); } // TEventList::Insert //======================================================================================== // CLASS TEventRetrieverCommand //======================================================================================== #undef Inherited #define Inherited TCommand #pragma segment MASelCommand MA_DEFINE_CLASS_M1(TEventRetrieverCommand, Inherited); //---------------------------------------------------------------------------------------- // TEventRetrieverCommand: Empty constructor to satisfy the compiler. //---------------------------------------------------------------------------------------- #pragma segment ConstructorRes TEventRetrieverCommand::TEventRetrieverCommand() { } // TEventRetrieverCommand::TEventRetrieverCommand //---------------------------------------------------------------------------------------- // TEventRetrieverCommand destructor //---------------------------------------------------------------------------------------- #pragma segment MADestructorRes TEventRetrieverCommand::~TEventRetrieverCommand() { } //---------------------------------------------------------------------------------------- // TEventRetrieverCommand::IEventRetrieverCommand: //---------------------------------------------------------------------------------------- #pragma segment MASelCommand void TEventRetrieverCommand::IEventRetrieverCommand(CommandNumber itsCommandNumber) { this->ICommand(itsCommandNumber, gDispatcher, kCantUndo, kDoesNotCauseChange, NULL); // Hang around fFreeOnCompletion = FALSE; fRecurring = TRUE; // Let more important stuff happen first fPriority = kPriorityLow; } // TEventRetrieverCommand::IEventRetrieverCommand //---------------------------------------------------------------------------------------- // TEventRetrieverCommand::NeedsToUnloadAllSegments: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TEventRetrieverCommand::NeedsToUnloadAllSegments() { return FALSE; } // TEventRetrieverCommand::NeedsToUnloadAllSegments //---------------------------------------------------------------------------------------- // TEventRetrieverCommand::DoIt: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TEventRetrieverCommand::DoIt() { gDispatcher->PollToolboxEvent(gDispatcher->fAllowApplicationToSleep); } // TEventRetrieverCommand::DoIt //======================================================================================== // CLASS TDispatcher //======================================================================================== #undef Inherited #define Inherited TCommandHandler #pragma segment MAInit MA_DEFINE_CLASS_M2(TDispatcher, Inherited, MDefaultScriptableObject); //---------------------------------------------------------------------------------------- // TDispatcher constructor //---------------------------------------------------------------------------------------- #pragma segment MAInit TDispatcher::TDispatcher() : MDefaultScriptableObject(cApplication) { // This is a special case. It needs to be available as soon as possible. gDispatcher = this; fMainFileType = 'TEXT'; fCreator = '\?\?\?\?'; fAllowApplicationToSleep = TRUE; fAlwaysTrackCursor = FALSE; fDone = FALSE; fProcessNumber.highLongOfPSN = kNoProcess; fProcessNumber.lowLongOfPSN = kNoProcess; fClickCount = 0; fEventList = NULL; fCursorRegion = NULL; fDocumentList = NULL; fEventLevel = 1; // Prevents UnloadAllSegs from getting called // if a modal dialogs is used befure starting // the main event loop fFreeWindowList = NULL; fHeadCohandler = NULL; fHelpRegion = NULL; fIdlePhase = idleEnd; fLastClickPart = inDesk; fLastMousePoint = gZeroPt; fLastUpTime = TickCount(); // fLaunchWithNewDocument = TRUE; fLowSpaceInterval = kLowSpaceInterval; fMainEventMask = everyEvent; #if qContainer fCADocumentList = NULL; gHasODFocus = TRUE; gHasODModalFocus = TRUE; if (gContainerLib) { fDisplayedMenus = kMBarOpenDoc; fCurrentDocument = 0; } else #endif fDisplayedMenus = kMBarDisplayed; fOtherMenus = kMBarNotDisplayed; fMBarHierarchical = kMBarHierarchical; fNextSpaceMessage = TickCount(); fSleepRegion = NULL; fSysWindowActive = FALSE; fTarget = this; fUndoCommand = cNoCommand; fRedoCommand = cNoCommand; // fUndoState = kShowUndo; // #if qDebug // fDebugFlagsWindow = NULL; // #endif fWantKeyUpEvents = FALSE; } // TDispatcher::TDispatcher //---------------------------------------------------------------------------------------- // TDispatcher destructor //---------------------------------------------------------------------------------------- #pragma segment MADestructorRes TDispatcher::~TDispatcher() { } //---------------------------------------------------------------------------------------- // TDispatcher::IDispatcher: //---------------------------------------------------------------------------------------- #pragma segment MAInit void TDispatcher::IDispatcher(OSType itsMainFileType, OSType itsCreator) { this->ICommandHandler(NULL); FailInfo fi; Try(fi) { fMainFileType = itsMainFileType; fCreator = itsCreator; fSleepRegion = MakeNewRgn(); fCursorRegion = MakeNewRgn(); fHelpRegion = MakeNewRgn(); FailOSErr(GetCurrentProcess(&fProcessNumber)); fFreeWindowList = NewList(); #if qDebug fFreeWindowList->SetEltType(&TWindow::fgClassDesc); #endif fDocumentList = NewList(); #if qDebug fDocumentList->SetEltType(&TDocument::fgClassDesc); #endif #if qContainer fCADocumentList = NewList(); //create list to hold list of container documents. fCADocumentList->IList(); #endif // Posted commands won't go anywhere until we create the queue TEventList * anEventList = new TEventList; anEventList->IEventList(); fEventList = anEventList; #if qDebug fEventList->SetEltType(&TEvent::fgClassDesc); #endif // Allocate the global dependencyspace gMacAppDependencySpace this->DoMakeDependencySpace(); // Make the command that operates the main Event Loop TEventRetrieverCommand * aEventCommand = new TEventRetrieverCommand; aEventCommand->IEventRetrieverCommand(cNoCommand); this->PostCommand(aEventCommand); // Create the MenuBar manager object gMenuBarManager = this->MakeMenuBarManager(); this->DoMakeViewServer(); // creates the view server // OSADispatcher setup if (!TOSADispatcher::fgDispatcher) InitUScripting(); TOSADispatcher::fgDispatcher->SetDefaultTarget(this); TPrintHandler::gPrintHandler->DispatcherIsAvailable(); fi.Success(); } else { #if qDebug ProgramBreak("Can't initialize the event loop object!"); #endif this->Free(); gDispatcher = NULL; fi.ReSignal(); } } // TDispatcher::IDispatcher //---------------------------------------------------------------------------------------- // TDispatcher::MakeMenuBarManager: //---------------------------------------------------------------------------------------- #pragma segment MAInit // This function is called by IDispatcher to create the menu bar manager object. TMenuBarManager* TDispatcher::MakeMenuBarManager() { TMenuBarManager* theMenuBarManager = new TMenuBarManager; theMenuBarManager->IMenuBarManager(fOtherMenus); return theMenuBarManager; } // TDispatcher::MakeMenuBarManager //---------------------------------------------------------------------------------------- // TDispatcher::AboutToLoseControl: //---------------------------------------------------------------------------------------- #pragma segment MAActivate void TDispatcher::AboutToLoseControl(Boolean convertClipboard) { gClipboardMgr->AboutToLoseControl(convertClipboard); // Let all windows know that we're losing control - e.g. so floaters can hide // themselves CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if (aWindow) aWindow->AboutToLoseControl(); } this->Changed(mAboutToLoseControl, this); this->ActivateBusyCursor(FALSE); // Don't want busy cursor while in DA } // TDispatcher::AboutToLoseControl //---------------------------------------------------------------------------------------- // TDispatcher::InteractWithUser: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes OSErr TDispatcher::InteractWithUser(long timeOutInTicks, NMRecPtr nmReqPtr, AEIdleUPP idleProc) { long interactTimeout; if (timeOutInTicks == kMacAppTimeout) { if (TOSADispatcher::fgDispatcher && TOSADispatcher::fgDispatcher->GetDispatchLevel() > 0) interactTimeout = kAEDefaultTimeout; else interactTimeout = kNoTimeOut; } else interactTimeout = timeOutInTicks; return AEInteractWithUser(interactTimeout, nmReqPtr, idleProc); } // TDispatcher::InteractWithUser //---------------------------------------------------------------------------------------- // TDispatcher::ActivateBusyCursor: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::ActivateBusyCursor(Boolean entering) { return (gBusyCursor ? gBusyCursor->Activate(entering) : FALSE); } // TDispatcher::ActivateBusyCursor //---------------------------------------------------------------------------------------- // TDispatcher::AddDocument: //---------------------------------------------------------------------------------------- #pragma segment MAOpen void TDispatcher::AddDocument(TDocument* aNewDocument) { if (fDocumentList) fDocumentList->Insert(aNewDocument); } // TDispatcher::AddDocument //---------------------------------------------------------------------------------------- // TDispatcher::AddWindow: //---------------------------------------------------------------------------------------- #pragma segment MAOpen void TDispatcher::AddWindow(TWindow* aWindow) { // Protect against double installation if (fFreeWindowList && (fFreeWindowList->GetIdentityItemNo(aWindow) == 0)) fFreeWindowList->Insert(aWindow); } // TDispatcher::AddWindow #if qContainer //---------------------------------------------------------------------------------------- // TDispatcher::AddCADocument: //---------------------------------------------------------------------------------------- #pragma segment MAOpen void TDispatcher::AddCADocument(TFileBasedDocument* aNewDocument) { //•••GJC //this needs better support other than a kludgy cast if (fCADocumentList) fCADocumentList->Insert((TObject*)aNewDocument); } // TDispatcher::AddCADocument #endif //---------------------------------------------------------------------------------------- // TDispatcher::AlertFilter: AlertFilter is a default filterProc used by MacAppAlert if // the filterProc passed in is NULL. It maps key strokes to the first character of button // item titles. It also hands off activate and update processing to gDispatcher if we're // not being called from an error condition or while nested. //---------------------------------------------------------------------------------------- #pragma segment MAGlobalsRes // Don't require a segment load for this Boolean TDispatcher::AlertFilter(DialogRef theDialog, EventRecord& theEvent, short& itemHit) { MAVolatileInit(Boolean, returnValue, FALSE); MAVolatileInit(Boolean, oldInFilterState, gInFilter); gInFilter = TRUE; // First call the minimal alert filter; if it does not handle the // event, do some more complex handling returnValue = MinimalAlertFilter(theDialog, theEvent, itemHit); if (returnValue == FALSE) { FailInfo fi; Try(fi) { // Wouldn't want MacApp to get lied to about where the focus _Actually_ is if (!gInhibitNestedHandling && !oldInFilterState) this->InvalidateFocus(); switch (theEvent.what) { // this is the first event the alert gets, use it to initialize the global buffer case activateEvt: case updateEvt: if ((((DialogRef)theEvent.message) != theDialog) && (!gInhibitNestedHandling && !oldInFilterState)) { GrafPtr savePort; GetPort(&savePort); Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); TToolboxEvent * event = new TToolboxEvent; AllocateObjectsFromPerm(oldObjectPerm); event->IToolboxEvent(this, theEvent); event->Process(); SetPort(savePort); } break; // let's determine if the key pressed corresponds to our button titles case keyDown: { static TToolboxEvent* bufferedKeyEvent; // Must be a global, since it's used each // time the alert filter is entered. (It // could be a field of TDispatcher...) Boolean needsSecondaryEvent = FALSE; if (!bufferedKeyEvent) { Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); bufferedKeyEvent = new TToolboxEvent; AllocateObjectsFromPerm(oldObjectPerm); needsSecondaryEvent = bufferedKeyEvent->IToolboxEvent(this, theEvent); } else bufferedKeyEvent->AddSecondaryKeyEvent(theEvent); if (!needsSecondaryEvent) { this->GetTarget()->KeyEventToComponents(bufferedKeyEvent);// Find out what keys were _REALLY_ pressed if (CompareAlertKeysToItem(theDialog, bufferedKeyEvent->fText, itemHit)) { DoAlertKeyDown(theDialog, itemHit); returnValue = TRUE; } bufferedKeyEvent = (TToolboxEvent*)FreeIfObject(bufferedKeyEvent); } } } // Idle but only if _REALLY_ necessary EventRecord anEvent; if (!gInhibitNestedHandling && !oldInFilterState && !EventAvail(everyEvent, &anEvent)) this->Idle(fIdlePhase); fi.Success(); } else // Recover { // Don't ReSignal -- called by Toolbox } } gInFilter = oldInFilterState; return returnValue; } // TDispatcher::AlertFilter //---------------------------------------------------------------------------------------- // TDispatcher::AppleEventIdleProc: //---------------------------------------------------------------------------------------- #pragma segment MAGlobalsRes // Don't require a segment load for this Boolean TDispatcher::AppleEventIdleProc(EventRecord& theEventRecord, long&/* sleepTime */ , RgnHandle&/* mouseRgn */ ) { if ((theEventRecord.what == activateEvt) || (theEventRecord.what == updateEvt)) { Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); TToolboxEvent* event = new TToolboxEvent; AllocateObjectsFromPerm(oldObjectPerm); event->IToolboxEvent(this, theEventRecord); event->Process(); } return FALSE; } // TDispatcher::AppleEventIdleProc //---------------------------------------------------------------------------------------- // TDispatcher::StandardFileFilter: //---------------------------------------------------------------------------------------- #pragma segment MAGlobalsRes // Don't require a segment load for this Boolean TDispatcher::StandardFileFilter(DialogRef /* theDialog */, EventRecord& theEvent, short& /* itemHit */, void* /* yourDataPtr */ ) { this->InvalidateFocus(); switch (theEvent.what) { case activateEvt: case updateEvt: // check if intended for a MacApp window if (!this->WMgrToWindow((WindowRef)theEvent.message)) break; // drop thru to processing the event case osEvt: case kHighLevelEvent: { GrafPtr savePort; GetPort(&savePort); // If the port get changed behind us // the dialog can't find its controls Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); TToolboxEvent* event = new TToolboxEvent; AllocateObjectsFromPerm(oldObjectPerm); event->IToolboxEvent(NULL, theEvent); ++fEventLevel; event->Process(); --fEventLevel; SetPort(savePort); } break; } return FALSE; // did not take the event } // TDispatcher::StandardFileFilter //---------------------------------------------------------------------------------------- // TDispatcher::FindDocument: //---------------------------------------------------------------------------------------- #pragma segment MAFile TDocument* TDispatcher::FindDocument(TFile* aFile) { CDocumentIterator iter(this); for (TDocument * aDocument = iter.FirstDocument(); iter.More(); aDocument = iter.NextDocument()) if (aDocument->FindDocument(aFile)) return aDocument; return NULL; // No document already open } // TDispatcher::FindDocument //---------------------------------------------------------------------------------------- // TDispatcher::Beep: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::Beep(short duration) { SysBeep(duration); } // TDispatcher::Beep //---------------------------------------------------------------------------------------- // TDispatcher::Close: //---------------------------------------------------------------------------------------- #pragma segment MATerminate void TDispatcher::Close() { // Close down the cohandler chain. Add a block for failure handling { CHandlerIterator iter(fHeadCohandler); for (TEventHandler * aHandler = iter.FirstHandler(); iter.More(); aHandler = iter.NextHandler()) FreeIfObject(aHandler); } gClipboardMgr->Close(); gViewServer = (TViewServer *)FreeIfObject(gViewServer); // won't be creating any more views... #if qAttachable // Toss any attached script this->FreeOSAScript(); #endif } // TDispatcher::Close //---------------------------------------------------------------------------------------- // TDispatcher::CloseToolboxWindow: //---------------------------------------------------------------------------------------- #pragma segment MAClose void TDispatcher::CloseToolboxWindow(WindowRef aWMgrWindow) { TWindow* aWindow = this->WMgrToWindow(aWMgrWindow); if (aWindow) aWindow->CloseByUser(cClose); else HideWindow(aWMgrWindow); } // TDispatcher::CloseToolboxWindow //---------------------------------------------------------------------------------------- // TDispatcher::CountClicks: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes short TDispatcher::CountClicks(TToolboxEvent* event, short whereMouseDown) { short newClickCount; newClickCount = 1; if ((whereMouseDown == fLastClickPart) && // clicked in the same place… (fClickCount > 0) && // not the first click… (event->fEventRecord.when - fLastUpTime < LMGetDoubleTime()) &&// close enough in time… this->GetTarget()->DoMultiClick(fLastMousePoint, event->fEventRecord.where))// close enough in space newClickCount = fClickCount + 1; fLastMousePoint = event->fEventRecord.where; fLastClickPart = whereMouseDown; fClickCount = newClickCount; return newClickCount; } // TDispatcher::CountClicks //---------------------------------------------------------------------------------------- // TDispatcher::DeleteDocument: //---------------------------------------------------------------------------------------- #pragma segment MAClose void TDispatcher::DeleteDocument(TDocument* docToDelete) { if (fDocumentList) fDocumentList->Delete(docToDelete); /* #if qContainer if (gContainerLib && !fDone && (!fDocumentList || (fDocumentList->fSize == 0))) this->DoMenuCommand(cQuit); #endif */ } // TDispatcher::DeleteDocument //---------------------------------------------------------------------------------------- // TDispatcher::DeleteWindow: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DeleteWindow(TWindow* windowToDelete) { if (fFreeWindowList) fFreeWindowList->Delete(windowToDelete); } // TDispatcher::DeleteWindow #if qContainer //---------------------------------------------------------------------------------------- // TDispatcher::DeleteCADocument: //---------------------------------------------------------------------------------------- #pragma segment MAClose void TDispatcher::DeleteCADocument(TFileBasedDocument* docToDelete) { //••• gjc this needs better support other than a kludgy cast if (fCADocumentList) fCADocumentList->Delete((TObject*)docToDelete); } // TDispatcher::DeleteDocument #endif //---------------------------------------------------------------------------------------- // TDispatcher::DispatchEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DispatchEvent(TToolboxEvent* event) { // For Toolbox events, fIdentifier == fEventRecord.what if (event) { #if qContainer if (gContainerLib && (event->fIdentifier != mouseDown)) { CAEventInfo eventInfo; Boolean handled = CADispatchEvent(&event->fEventRecords[0], &eventInfo); if (event->fDoubleEvent) handled = CADispatchEvent(&event->fEventRecords[1], &eventInfo); if (handled) return; } #endif switch (event->fIdentifier) { case mouseUp: this->HandleMouseUp(event); break; case mouseDown: this->HandleMouseDown(event); break; case activateEvt: this->HandleActivateEvent(event); break; case updateEvt: this->HandleUpdateEvent(event); break; case keyDown: case autoKey: this->HandleKeyDownEvent(event); break; case keyUp: // A MultiFinder™ bug (at least up to 6.0) keep us from reliably getting // keyUp events after minor context switches (background updates, etc.). // It replaces the global event mask (which we would have had to change to // get keyups in the first place) with the wrong mask. Fixed in system 7.0 this->HandleKeyUpEvent(event); break; case diskEvt: this->HandleDiskEvent(event); break; case osEvt: this->HandleSystemEvent(event); break; case kHighLevelEvent: this->HandleHighLevelEvent(event); break; default: this->HandleAlienEvent(event); break; } } } // TDispatcher::DispatchEvent //---------------------------------------------------------------------------------------- // TDispatcher::DoCommandKeyEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DoCommandKeyEvent(TToolboxEvent* event)// override { if (!event->IsAutoKeyEvent()) { this->SetupTheMenus(); // == THIS ======================================================================================= // Optional support for case sensitive command keys. // Use the following line because // KeyEventToComponents returns the correct character for shifted keys when the // command key is down. That lets us test for things like command-period // correctly. So in order to be backward compatible (sigh) we now have to ignore // the _correct_ char that is passed in (and is in event->fText) and use the // old ToolBox supplied unPasteurized character that is left in the actual // EventRecord // // long menuKeyResult = MenuKey(event->fText[1]); // if (event->fDoubleEvent) // menuKeyResult = MenuKey(event->fText[2]); // == OR THIS ==================================================================================== // Optional support for the latest version (1.2) of Mercutio MDEF which allows the // display and processing of Option and Shifted command keys. // http://camis.stanford.edu/people/felciano/personal/mercutio/index.html // // const mMercutioMenu = xxx; // ID of any menu that uses the Mercutio MDEF // // MenuHandle anMHandle = MAGetMenu(mMercutioMenu); // long menuKeyResult = MDEF_MenuKey(event->fEventRecords[0].message, event->fEventRecords[0].modifiers, anMHandle); // if (event->fDoubleEvent) // menuKeyResult = MDEF_MenuKey(event->fEventRecords[1].message, event->fEventRecords[1].modifiers, anMHandle); // == OR THIS ==================================================================================== // Ordinary case and modifier insensitive command keys long menuKeyResult = MenuKey((unsigned char)(((event->fEventRecords[0].message) & charCodeMask))); if (event->fDoubleEvent) menuKeyResult = MenuKey((unsigned char)(((event->fEventRecords[1].message) & charCodeMask))); this->DispatchMenuEvent(event, menuKeyResult); } else Inherited::DoCommandKeyEvent(event); } // TDispatcher::DoCommandKeyEvent //---------------------------------------------------------------------------------------- // TDispatcher::DoKeyEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DoKeyEvent(TToolboxEvent* event)// override { CommandNumber aCommand = cNoCommand; switch (event->fKeyCode) { case kF1VirtualCode: aCommand = cUndo; break; case kF2VirtualCode: aCommand = cCut; break; case kF3VirtualCode: aCommand = cCopy; break; case kF4VirtualCode: aCommand = cPaste; break; case kClearVirtualCode: aCommand = cClear; break; } if (aCommand != cNoCommand) { this->SetupTheMenus(); if (CommandEnabled(aCommand)) this->GetTarget()->HandleMenuCommand(aCommand); } else Inherited::DoKeyEvent(event); } // TDispatcher::DoKeyEvent //---------------------------------------------------------------------------------------- // TDispatcher::DoMakeDocument: //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- // TDispatcher::DoMakeFile: //---------------------------------------------------------------------------------------- #pragma segment MAOpen TFile* TDispatcher::DoMakeFile(CommandNumber) { return NewFile(fMainFileType, fCreator, kUsesDataFork, kUsesRsrcFork, !kDataOpen, !kRsrcOpen); } // TDispatcher::DoMakeFile //---------------------------------------------------------------------------------------- // TDispatcher::DoMenuCommand: //---------------------------------------------------------------------------------------- #pragma segment MASelCommand void TDispatcher::DoMenuCommand(CommandNumber aCommandNumber) { // =================================================================================== // Some commands will be posted to perform actions that must _ALWAYS_ be available. // The allocation cannot be allowed to fail. So we do a temp allocation which by // definition cannot be allowed to fail. This strategy is used wherever we want to use // command objects but don't want to leave the user twisting in the breeze. NOTE: // Don't forget to allow for this memory in your mem! resource if you copy this style // in your own code. // =================================================================================== switch (aCommandNumber) { case cUndo: { Boolean oldTempAlloc = TemporaryAllocation(TRUE); Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); TUndoCommand* undoCommand = new TUndoCommand; undoCommand->IUndoCommand(aCommandNumber); undoCommand->fUseAppleEvent = TRUE; this->PostCommand(undoCommand); TemporaryAllocation(oldTempAlloc); AllocateObjectsFromPerm(oldObjectPerm); } break; case cRedo: { Boolean oldTempAlloc = TemporaryAllocation(TRUE); Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); TRedoCommand* redoCommand = new TRedoCommand; redoCommand->IRedoCommand(aCommandNumber); redoCommand->fUseAppleEvent = TRUE; this->PostCommand(redoCommand); TemporaryAllocation(oldTempAlloc); AllocateObjectsFromPerm(oldObjectPerm); } break; case cClose: #if qDebug if (this->WMgrToWindow(FrontWindow())) ProgramBreak("The frontmost window is a window object but didn't handle the cClose CommandNumber, your TWindow subclass probably forgot to call Inherited::DoMenuCommand!"); #endif this->CloseToolboxWindow(FrontWindow());// TWindow would have handled the command // before we get here so the window is break; // probably a DA or something default: Inherited::DoMenuCommand(aCommandNumber); break; } } // TDispatcher::DoMenuCommand //---------------------------------------------------------------------------------------- // TDispatcher::DoSetupMenus: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DoSetupMenus() { Inherited::DoSetupMenus(); gMenuBarManager->SetPreferredMenuBarID(fDisplayedMenus); gMenuBarManager->SetPreferredHierMenuBarID(fMBarHierarchical); Boolean lowSpace = MemSpaceIsLow(); Enable(-(mApple << 8), TRUE); // allow the whole menu WindowRef aWindowPtr = FrontWindow(); if ((aWindowPtr) && (this->WMgrToWindow(aWindowPtr) == NULL)) // window objects will take care of themselves, but we take care of the indigent. Enable(cClose, GetWindowGoAwayFlag(aWindowPtr)); } // TDispatcher::DoSetupMenus //---------------------------------------------------------------------------------------- // TDispatcher::DoMakeDependencySpace: //---------------------------------------------------------------------------------------- #pragma segment MAInit void TDispatcher::DoMakeDependencySpace() { TSimpleDependencySpace* aDependencySpace = NULL; aDependencySpace = new TSimpleDependencySpace; aDependencySpace->ISimpleDependencySpace(); gMacAppDependencies = aDependencySpace; } //---------------------------------------------------------------------------------------- // TDispatcher::GetDefaultCursorRegion: Make the region the desktop less the active // window, and any first click windows. The current mouse location is added in // TDispatcher::TrackCursor. //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::GetDefaultCursorRegion(CPoint /* globalMouse */, RgnHandle cursorRegion) { // Start off with the "desktop region" GetDeskTopRegion(cursorRegion); // Remove the content of all windows for which TestWindow returns true CTemporaryRegion windowContent; CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if (aWindow && aWindow->IsShown() #if !qDrag && aWindow->HandlesCursor() #endif && aWindow->Focus()) { aWindow->GetVisibleRegion(windowContent); // Convert the content to global coordinates. We focused on the window because // the content is in the coordinates of the current port aWindow->LocalToSuperRegion(windowContent); // Remove the visRgn from the cursor region DiffRgn(cursorRegion, windowContent, cursorRegion); } } } // TDispatcher::GetDefaultCursorRegion //---------------------------------------------------------------------------------------- // TDispatcher::InstallHelpMenuItems: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::InstallHelpMenuItems() { // abstract method; override to install your help menu item(s). Use // gMenuBarManager->AddHelpMenuItem( "^0 Help", kYourHelpCommandNumber ); } // TDispatcher::InstallHelpMenuItems //---------------------------------------------------------------------------------------- // TDispatcher::GetDefaultHelpRegion: Make the region the desktop less the active window, // and any first click windows. The current mouse location is added in // TDispatcher::TrackHelp. //---------------------------------------------------------------------------------------- void TDispatcher::GetDefaultHelpRegion(CPoint /* globalMouse */, RgnHandle helpRegion) { // Start off with the "desktop region" GetDeskTopRegion(helpRegion); // Remove the content of all windows for which TestWindow returns true CTemporaryRegion windowContent; CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if (aWindow && (aWindow->IsShown() && aWindow->HandlesHelp()) && aWindow->Focus()) { aWindow->GetVisibleRegion(windowContent); // Convert the content to global coordinates. We focused on the window because // the content is in the coordinates of the current port aWindow->LocalToSuperRegion(windowContent); // Remove the visRgn from the cursor region DiffRgn(helpRegion, windowContent, helpRegion); } } } // TDispatcher::GetDefaultHelpRegion //---------------------------------------------------------------------------------------- // TDispatcher::GetHelpParameters: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::GetHelpParameters(ResNumber helpResource, short helpIndex, short helpState, HMMessageRecord& helpMessage, CPoint& localQDTip, CRect& localQDRect, short& balloonVariant) { MAVolatileInit(short, oldResFile, MACurResFile()); FailInfo fi; Try(fi) { MAUseResFile(gApplicationRefNum); unsigned long options; short theProc; short count; FailOSErr(HMGetIndHelpMsg(kHMDialogResType, helpResource, helpIndex, helpState, &options, localQDTip, localQDRect, &theProc, &balloonVariant, &helpMessage, &count)); fi.Success(); } else { MAUseResFile(oldResFile); fi.ReSignal(); } MAUseResFile(oldResFile); } // TDispatcher::GetHelpParameters //---------------------------------------------------------------------------------------- // TDispatcher::GetSleepRegion: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes RgnHandle TDispatcher::GetSleepRegion() { if (this->IsFrontProcess()) { // Compute based on where the mouse is right NOW CPoint globalMouse; GetMouse(globalMouse); LocalToGlobal(globalMouse); Boolean isSleepInvalid = FALSE; // The help region is computed before the cursor rgn so that // the cursor region excludes the balloon shape if ((this->IsHelpRgnInvalid()) && (this->IsHelpEnabled())) { this->TrackHelp(globalMouse); isSleepInvalid = TRUE; } if (this->IsCursorRgnInvalid()) { this->TrackCursor(globalMouse); isSleepInvalid = TRUE; } if (isSleepInvalid) if (this->IsHelpEnabled()) SectRgn(fCursorRegion, fHelpRegion, fSleepRegion); else CopyRgn(fCursorRegion, fSleepRegion); // Ensure that the sleep region contains the mouse. TView::PtAndRgn(globalMouse, fSleepRegion); return fSleepRegion; } else return NULL; } // TDispatcher::GetSleepRegion //---------------------------------------------------------------------------------------- // TDispatcher::GetEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes TToolboxEvent* TDispatcher::GetEvent(short eventMask, long sleep, RgnHandle sleepRegion) { TToolboxEvent * returnEvent = NULL; if (--gRsrcCheck <= 0) { CheckRsrcUsage(); gRsrcCheck = kRsrcCheckInterval; } #if qDebug if (gIntenseDebugging && gReportEvent) { fprintf(stderr, "WaitNextEvent: sleep=0%d", sleep); // faceless driver bug fixed in MF 7.0 if (sleepRegion == NULL) fprintf(stderr, ", sleep region=NULL"); else { CRect bBox((*sleepRegion)->rgnBBox); fprintf(stderr, ", sleep region = %s", (const char*) bBox); } fprintf(stderr, "\n"); } if (gShowCursorRegion || gShowHelpRegion || gShowSleepRegion) { if (gShowCursorRegion) ShowGlobalRegion(fCursorRegion); if (gShowHelpRegion) ShowGlobalRegion(fHelpRegion); if (gShowSleepRegion) ShowGlobalRegion(fSleepRegion); sleep = 60; } #endif // qDebug // If we are in a nested event level than don't turn off the busy cursor since we are // probably in the middle of an idle or filter proc and don't want to turn on and off // the busy cursor each time it gets to service an event. if (fEventLevel <= 1) this->ActivateBusyCursor(FALSE); // Turn off busy cursor while we're away. #if qPerform Boolean oldSetting = PerfMonitorEnabled(); #endif // SystemEvents aren't queued and will be lost if not retrieved when available. So we // ensure here that they are always retrieved by adding osMask. EventRecord anEvent; if (WaitNextEvent(eventMask | osMask, &anEvent, sleep, sleepRegion)) { // MWERKS you can remove the following 3 lines if you always send debug messages to your debugger // instead of to SIOUX #if defined(__MWERKS__) && (qDebug || qTheDebugger) if (!CWDebugHandleOneEvent(&anEvent)) #endif { Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); returnEvent = new TToolboxEvent; AllocateObjectsFromPerm(oldObjectPerm); if (returnEvent->IToolboxEvent(this, anEvent)) { // The event was part of a pair used to input 16 bit characters // Retrieve the second half of the pair immediately. EventRecord secondaryEvent; if (GetOSEvent(keyDownMask | keyUpMask | autoKeyMask, &secondaryEvent)) returnEvent->AddSecondaryKeyEvent(secondaryEvent); } } } #if qPerform EnablePerfMonitor(oldSetting); #endif if (this->IsFrontProcess()) // If we're not in the background, then this->ActivateBusyCursor(TRUE); // …enable the busy cursor mechanism. return returnEvent; } // TDispatcher::GetEvent //---------------------------------------------------------------------------------------- // TDispatcher::GetFrontWindow: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes TWindow* TDispatcher::GetFrontWindow() { CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if ((aWindow) && (aWindow->IsShown()) && (!aWindow->fFloats)) return aWindow; } return NULL; } // TDispatcher::GetFrontWindow //---------------------------------------------------------------------------------------- // TDispatcher::GetActiveWindow: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes TWindow* TDispatcher::GetActiveWindow(Boolean floatersAreOkay) { CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if ((aWindow) && (aWindow->IsShown()) && (aWindow->IsActive())) { if (aWindow->fFloats) { if (floatersAreOkay) return aWindow; } else return aWindow; } } return NULL; } // TDispatcher::GetActiveWindow //---------------------------------------------------------------------------------------- // TDispatcher::RetrieveAnEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes TEvent* TDispatcher::RetrieveAnEvent() // override { TEvent* returnEvent = NULL; // Higher priority events are at the end of the list. CEventListIterator iter(fEventList); for (TEvent* itsEvent = iter.FirstEvent(); iter.More(); itsEvent = iter.NextEvent()) { if (itsEvent->IsReadyToExecute()) { returnEvent = itsEvent; break; } } RemoveEvent(returnEvent); return returnEvent; } // TDispatcher::RetrieveAnEvent //---------------------------------------------------------------------------------------- // TDispatcher::RemoveEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::RemoveEvent(TEvent* event) { if ((event != NULL) && !event->IsRecurring() && (fEventList != NULL)) fEventList->Delete(event); } //---------------------------------------------------------------------------------------- // TDispatcher::NewToolboxWindow: //---------------------------------------------------------------------------------------- #pragma segment MAOpen #if PRAGMA_ALIGN_SUPPORTED #pragma options align=mac68k #endif struct WINDTemplate { CRect bounds; short procID; Boolean visible; Boolean filler1; Boolean goAway; Boolean filler2; long refcon; short itemsID; // only for DLOG resource }; #if PRAGMA_ALIGN_SUPPORTED #pragma options align=reset #endif typedef struct WINDTemplate WINDTemplate; typedef WINDTemplate *WINDTemplatePtr, **WINDTemplateHandle; WindowRef TDispatcher::NewToolboxWindow(Ptr storage, short rsrcId, Boolean& isResizable, Boolean& isClosable) { // We force INVISIBLE in the WIND definition so the screen won't flash. WindowRef aWMgrWindow; WINDTemplateHandle templateHandle; // Even though the window is permanent, we allocate it under a temporary flag so that the // maximum memory is available. Quickdraw can blow up if it can't allocate a grafPort. MAVolatileInit(Boolean, oldPerm, PermAllocation(FALSE)); FailInfo fi; Try(fi) { templateHandle = (WINDTemplateHandle)GetResource('WIND', rsrcId); FailNILResource((Handle)templateHandle); MoveHHi((Handle)templateHandle); // in case it is locked by the ROM WINDTemplate & templateData = **templateHandle; templateData.visible = FALSE; isClosable = templateData.goAway; isResizable = ((templateData.procID == documentProc) || (templateData.procID == zoomDocProc) || (((templateData.procID & 0xFFF0) == kSystem75_kWindoidWDEF) && ((templateData.procID & 0x000F) & kSystem75_hasGrow)) || (((templateData.procID & 0xFFF0) == kSystem75AndLess_kWindoidWDEF) && ((templateData.procID & 0x000F) & kSystem75_hasGrow)) #if qUseOldFloatingWDEF || (((templateData.procID & 0xFFF0) == kWindoidWDEF) && !((templateData.procID & 0x000F) & kWindoidNotResizable)) #endif ); // If your own defProc is resizable, too, then after the call on NewToolboxWindow, set // isResizable true WindowRef putWindowBehind = TWindow::GetLastFloatingWindowPtr(); if (putWindowBehind == NULL) putWindowBehind = (WindowRef) -1; if (qNeedsColorQD || HasColorQD()) aWMgrWindow = (WindowRef)(GetNewCWindow(rsrcId, (Ptr)(storage), putWindowBehind)); else aWMgrWindow = GetNewWindow(rsrcId, (Ptr)(storage), putWindowBehind); FailNIL(aWMgrWindow); oldPerm = PermAllocation(oldPerm); fi.Success(); } else // Recover. Don't need the failure handler since we've set the perm allocation flag back. { // Make sure the perm allocation flag is set back to what it was // when we entered NewToolboxWindow. oldPerm = PermAllocation(oldPerm); fi.ReSignal(); } // Now we must make sure that the code reserve is still intact. if (!CheckReserve()) { aWMgrWindow = TWindow::FreeIfWMgrWindow(aWMgrWindow, storage == NULL); Failure(memFullErr, 0); } return aWMgrWindow; } // TDispatcher::NewToolboxWindow //---------------------------------------------------------------------------------------- // TDispatcher::GetTarget: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes TEventHandler* TDispatcher::GetTarget() { return fTarget; } // TDispatcher::GetTarget //---------------------------------------------------------------------------------------- // TDispatcher::HandleActivateEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleActivateEvent(TToolboxEvent* event) { TWindow * aWindow = this->WMgrToWindow((WindowRef)(event->fEventRecord.message)); if (aWindow) { Boolean activate = ((event->fEventRecord.modifiers) & activeFlag) != 0; if (aWindow->fFloats) // ignore floaters { TWindow* frontWindow = this->GetFrontWindow(); // find frontmost non-floating window if (frontWindow) { aWindow = frontWindow; // (de)activate it instead of the floater HiliteWindow(aWindow->fWMgrWindow, activate); } } aWindow->Activate(activate); } else this->HandleAlienEvent(event); } // TDispatcher::HandleActivateEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleAlienEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleAlienEvent(TToolboxEvent* event) { CHandlerIterator iter(fHeadCohandler); for (TEventHandler * aHandler = iter.FirstHandler(); iter.More(); aHandler = iter.NextHandler()) if (aHandler->DoCoHandlerEvent(event)) break; } // TDispatcher::HandleAlienEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleDiskEvent: //---------------------------------------------------------------------------------------- #pragma segment MADoCommand void TDispatcher::HandleDiskEvent(TToolboxEvent* event) { if (HiWord(event->fEventRecord.message) != noErr) { short err = DIBadMount(CPoint(112, 80), event->fEventRecord.message); #if qDebugMsg if (err != noErr) fprintf(stderr, "error from DIBadMount is %d\n", err); #endif } } // TDispatcher::HandleDiskEvent //---------------------------------------------------------------------------------------- // TDispatcher::DoToolboxEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DoToolboxEvent(TToolboxEvent* event) { #if qDebug if (gReportEvent && event) event->ReportEvent(); #endif this->DispatchEvent(event); } // TDispatcher::DoToolboxEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleHighLevelEvent: Assume that the high level event received was an // Apple Event and process it. This will dispatch to us via MAGeneralDispatch. //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleHighLevelEvent(TToolboxEvent* event) { this->SetupTheMenus(); // Make sure that the menus are setup // correctly before we handle the event EventRecord anEventRecord = event->fEventRecord; OSErr theErr = AEProcessAppleEvent(&anEventRecord); } // TDispatcher::HandleHighLevelEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleKeyDownEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleKeyDownEvent(TToolboxEvent* event) { this->GetTarget()->KeyEventToComponents(event);// Find out what keys were _REALLY_ pressed if (event->IsCommandKeyPressed()) this->GetTarget()->HandleCommandKey(event); else this->GetTarget()->HandleKeyCommand(event); } // TDispatcher::HandleKeyDownEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleKeyUpEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleKeyUpEvent(TToolboxEvent* event) { // We don't think KeyUp events should affect the menus. event->fAffectsMenus = FALSE; this->GetTarget()->KeyEventToComponents(event);// Find out what keys were _REALLY_ released this->GetTarget()->HandleKeyUp(event); } // TDispatcher::HandleKeyUpEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleMouseDown: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleMouseDown(TToolboxEvent* event) { WindowRef aWMgrWindow; short whereMouseDown = FindWindow(event->fEventRecord.where, &aWMgrWindow); event->fClickCount = this->CountClicks(event, whereMouseDown); TWindow * aWindow = this->WMgrToWindow(aWMgrWindow); #if qContainer Boolean proceed = TRUE; if (gContainerLib) { if (whereMouseDown != inMenuBar) { CAEventInfo eventInfo; Boolean proceed = !CADispatchEvent(&event->fEventRecords[0], &eventInfo); if (event->fDoubleEvent) proceed = !CADispatchEvent(&event->fEventRecords[1], &eventInfo); } } #endif if ((whereMouseDown != inMenuBar) && this->InModalState() && (aWindow != (this->GetActiveWindow(kNoFloaters)))) { // // Allow command drag of behind windows // if ((whereMouseDown != inDrag) || !event->IsCommandKeyPressed()) { this->Beep(2); return; // exit(HandleMouseDown); } } #if qContainer if (proceed) #endif { switch (whereMouseDown) { case inMenuBar: { // 3.5 this->SetupTheMenus(); // gives application a chance to setup individual menu items SetCursor(&(qd.arrow)); long menuItem = MenuSelect(event->fEventRecord.where); this->DispatchMenuEvent(event, menuItem); } break; case inSysWindow: { EventRecord anEventRecord = event->fEventRecord; SystemClick(&anEventRecord, (WindowPtr)aWMgrWindow); } break; default: // if a MacApp window was associated with the WindowRef then let the window object decide // what to do with the mouse click if (aWindow) { if (aWindow->Focus()) // if we can't focus, we're in trouble { VPoint theMouse(event->fEventRecord.where); aWindow->SuperToLocal(theMouse); aWindow->HandleMouseDown(theMouse, event, gStdHysteresis); } #if qDebug else ProgramBreak("In TDispatcher::HandleMouseDown: couldn't focus on a window object!"); #endif } else this->HandleAlienEvent(event); break; } } // 3.5 fLastUpTime = TickCount(); // Because the toolbox often eats mouseUpEvents remember the time on the way out for // double/ triple detection. } // TDispatcher::HandleMouseDown //---------------------------------------------------------------------------------------- // TDispatcher::HandleMouseUp: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleMouseUp(TToolboxEvent* event) { // now we _Really_ know what the last mouse up time is. // Remember time of last mouse up, in order to detect double/triple (multiple) clicks fLastUpTime = event->fEventRecord.when; WindowRef aWMgrWindow; short whereMouseDown = FindWindow(event->fEventRecord.where, &aWMgrWindow); switch (whereMouseDown) { case inMenuBar: break; case inSysWindow: break; default: // if a MacApp window was associated with the WindowRef then let the window object decide { TWindow * aWindow = this->WMgrToWindow(aWMgrWindow); // what to do with the mouse click if (aWindow) { if (aWindow->Focus()) // if we can't focus, we're in trouble { VPoint theMouse(event->fEventRecord.where); aWindow->SuperToLocal(theMouse); aWindow->HandleMouseUp(theMouse, event, gStdHysteresis); } #if qDebug else ProgramBreak("In TDispatcher::HandleMouseUp: couldn't focus on a window object!"); #endif } else this->HandleAlienEvent(event); } break; } } // TDispatcher::HandleMouseUp //---------------------------------------------------------------------------------------- // TDispatcher::HandleSystemEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleSystemEvent(TToolboxEvent* event) { switch (((unsigned long)(event->fEventRecord.message & osEvtMessageMask)) >> 24) { case suspendResumeMessage: { Boolean switchingIn = ((event->fEventRecord.message) & resumeFlag) != 0; Boolean convertClipboard = ((event->fEventRecord.message) & convertClipboardFlag) != 0; if (switchingIn) { // the Proces Manager may have activated the wrong window (if, when // we suspended earlier, we had non-floating window(s) that hide on suspend // such as the clipboard) so we augment what it did by activating the // right one! if (TWindow::MAFrontWindow() != NULL) TWindow::MADeactivateWindow(TWindow::MAFrontWindow()); this->RegainControl(convertClipboard); TWindow * aWindow = this->GetFrontWindow(); if (aWindow) TWindow::MAActivateWindow(aWindow->fWMgrWindow); } else { // When switching out, after having hid windows that get hid on suspend in // AboutToLoseControl, we need to ensure that our idea about the front // window and the Process Mgr's idea about the front window are the same. // (note that we do the second half of the work when we get the resume // event). WindowRef theFrontWindow = TWindow::MAFrontWindow();// remember the front window this->AboutToLoseControl(convertClipboard);// might hide windows… TWindow * aWindow = this->GetActiveWindow(FALSE); if (aWindow) TWindow::MADeactivateWindow(aWindow->fWMgrWindow); } this->InvalidateMouseRegions(); } break; case mouseMovedMessage: event->fAffectsMenus = FALSE; // We don't think mouse tracking usually // bothers the menus. We got the mouse // moved event because the mouse strayed // outside of fSleepRegion. It may or may // not have strayed outside of the other // mouse regions. We'll only invalidate // them here (if necessary) because that // way we can defer computing them for as // long as possible. if (!PtInRgn(event->fEventRecord.where, fCursorRegion)) this->InvalidateCursorRgn(); if (!PtInRgn(event->fEventRecord.where, fHelpRegion)) this->InvalidateHelpRgn(); break; default: #if qDebugMsg if (gIntenseDebugging) fprintf(stderr, "in TDispatcher.HandleSystemEvent: got unrecognized event\n"); #endif break; } } // TDispatcher::HandleSystemEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleToolboxEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleToolboxEvent(TToolboxEvent* event) { FailInfo fi; Try(fi) { Boolean proceed = TRUE; TBehavior* aBehavior = this->GetFirstEnabledBehavior(); if (aBehavior) proceed = !aBehavior->DoToolboxEvent(event); if (proceed) this->DoToolboxEvent(event); fi.Success(); } else // Recover { this->DidEvent(event); fi.ReSignal(); } this->DidEvent(event); } // TDispatcher::HandleToolboxEvent //---------------------------------------------------------------------------------------- // TDispatcher::HandleUpdateEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleUpdateEvent(TToolboxEvent* event) { // We don't think that update events should affect menus. event->fAffectsMenus = FALSE; TWindow * aWindow = this->WMgrToWindow((WindowRef)event->fEventRecord.message); if (aWindow) aWindow->Update(); else this->HandleAlienEvent(event); } // TDispatcher::HandleUpdateEvent //---------------------------------------------------------------------------------------- // TDispatcher::Idle: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::Idle(IdlePhase phase) { FailInfo fi; Try(fi) { if (phase == idleBegin) { if (!gInFilter) { #if qSegments if (fEventLevel == 1 /*&& MemSpaceIsLow()*/) // Don't unload segs if nested event handling UnloadAllSegments(); #endif if (MemSpaceIsLow()) this->SpaceIsLowAlert(); else fNextSpaceMessage = TickCount(); } } else if (phase == idleContinue) { #if qAttachable // Give an attached script some idle time IdleOSAScript(); #endif #if qContainer //Give the contained parts, if any, Idle time. EventRecord theEventRecord; theEventRecord.what = nullEvent; theEventRecord.message = nullEvent; theEventRecord.when = TickCount(); CAEventInfo eventInfo; Boolean eventHandled = CADispatchEvent(&theEventRecord, &eventInfo); //ignoring if it was handled or not, for now #endif } // Create a new block for failure handling { CHandlerIterator iter(fHeadCohandler); for (TEventHandler * aHandler = iter.FirstHandler(); iter.More(); aHandler = iter.NextHandler()) aHandler->HandleIdle(phase); } #if qDebug Assertion(this->GetTarget() != NULL, "GetTarget != NULL"); #endif // Create a new block for failure handling { CHandlerIterator iter(this->GetTarget()); for (TEventHandler * aHandler = iter.FirstHandler(); iter.More(); aHandler = iter.NextHandler()) aHandler->HandleIdle(phase); } fi.Success(); } else // Recover { #if qDebugMsg fprintf(stderr, "Idle failed\n"); #endif } } // TDispatcher::Idle //---------------------------------------------------------------------------------------- // TDispatcher::GetWaitTicks: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes long TDispatcher::GetWaitTicks(Boolean allowApplicationToSleep) { const short kMaxSleep = 60; // max sleep in foreground so MultiFinder // gives time to non-desk accessory drivers long returnValue = 0; if (allowApplicationToSleep) { long compositeTicks = kMaxIdleTime; // Check the cohandler chain first. Add new block for failure handling { CHandlerIterator iter(fHeadCohandler); for (TEventHandler * aHandler = iter.FirstHandler(); iter.More(); aHandler = iter.NextHandler()) compositeTicks = MinMax(0, aHandler->NextIdle() - TickCount(), compositeTicks); } #if qDebug Assertion(this->GetTarget() != NULL, "GetTarget != NULL"); #endif // now run through the target chain. Add new block for failure handling { CHandlerIterator iter(this->GetTarget()); for (TEventHandler * aHandler = iter.FirstHandler(); iter.More(); aHandler = iter.NextHandler()) compositeTicks = MinMax(0, aHandler->NextIdle() - TickCount(), compositeTicks); } returnValue = compositeTicks; } return returnValue; } // TDispatcher::GetWaitTicks //---------------------------------------------------------------------------------------- // TDispatcher::InModalState: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::InModalState() { WindowRef aWindowPtr = FrontWindow(); // in case the front window is an alert or something if ((this->WMgrToWindow(aWindowPtr) == NULL) && (aWindowPtr)) switch (GetWindowVariant(aWindowPtr)) { case dBoxProc: case plainDBox: case altDBoxProc: return TRUE; default: return FALSE; } else { TWindow * aWindow = this->GetActiveWindow(kNoFloaters); return (aWindow && aWindow->IsInModalState()); } } // TDispatcher::InModalState //---------------------------------------------------------------------------------------- // TDispatcher::InstallCohandler: //---------------------------------------------------------------------------------------- #pragma segment MANonRes void TDispatcher::InstallCohandler(TEventHandler* aCohandler, Boolean addIt) { if (addIt) fHeadCohandler = aCohandler->AddHandler(fHeadCohandler); else fHeadCohandler = aCohandler->RemoveHandler(fHeadCohandler); } // TDispatcher::InstallCohandler //---------------------------------------------------------------------------------------- // TDispatcher::IsFrontProcess: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::IsFrontProcess() { ProcessSerialNumber aPSN; ProcessSerialNumber applicationPSN; Boolean result; FailOSErr(GetFrontProcess(&aPSN)); applicationPSN = fProcessNumber; FailOSErr(SameProcess(&aPSN, &applicationPSN, &result)); return result; } // TDispatcher::IsFrontProcess //---------------------------------------------------------------------------------------- // TDispatcher::MakeFrontProcess: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::MakeFrontProcess() { if (!this->IsFrontProcess()) { ProcessSerialNumber aPSN = fProcessNumber; FailOSErr(SetFrontProcess(&aPSN)); } } // TDispatcher::MakeFrontProcess //---------------------------------------------------------------------------------------- // TDispatcher::WakeProcess: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::WakeProcess() { ProcessSerialNumber aPSN = fProcessNumber; FailOSErr(WakeUpProcess(&aPSN)); } //---------------------------------------------------------------------------------------- // TDispatcher::IsHelpEnabled: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::IsHelpEnabled() { return HMGetBalloons(); } // TDispatcher::IsHelpEnabled //---------------------------------------------------------------------------------------- // TDispatcher::InvalidateMouseRegions: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::InvalidateMouseRegions() { this->InvalidateCursorRgn(); this->InvalidateHelpRgn(); } // TDispatcher::InvalidateMouseRegions //---------------------------------------------------------------------------------------- // TDispatcher::InvalidateCursorRgn: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::InvalidateCursorRgn() { if (fCursorRegion) SetEmptyRgn(fCursorRegion); // Make sure it gets changed back } // TDispatcher::InvalidateCursorRgn //---------------------------------------------------------------------------------------- // TDispatcher::InvalidateHelpRgn: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::InvalidateHelpRgn() { if (fHelpRegion) SetEmptyRgn(fHelpRegion); // Make sure it gets changed back if (this->IsFrontProcess() && HMIsBalloon()) { OSErr err = HMRemoveBalloon(); if (err != hmNoBalloonUp) FailOSErr(err); } } // TDispatcher::InvalidateHelpRgn //---------------------------------------------------------------------------------------- // TDispatcher::InvalidateFocus: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::InvalidateFocus() { if (TView::gFocusedView) TView::gFocusedView->InvalidateFocus(); } // TDispatcher::InvalidateFocus //---------------------------------------------------------------------------------------- // TDispatcher::IsCursorRgnInvalid: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::IsCursorRgnInvalid() { // The cursor is normally tracked via MouseMoved events. But for those with special // needs fAlwaysTrackCursor can come to the rescue. return (EmptyRgn(fCursorRegion) || fAlwaysTrackCursor); } // TDispatcher::IsCursorRgnInvalid //---------------------------------------------------------------------------------------- // TDispatcher::IsHelpRgnInvalid: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::IsHelpRgnInvalid() { return EmptyRgn(fHelpRegion); } // TDispatcher::IsHelpRgnInvalid //---------------------------------------------------------------------------------------- // TDispatcher::KeyEventToComponents: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::KeyEventToComponents(TToolboxEvent* event) // See Tech Note #263 for the reason for this abomination { Inherited::KeyEventToComponents(event); // Get default translation, if any if ((event->fEventRecord.what == keyDown) || (event->fEventRecord.what == keyUp) || (event->fEventRecord.what == autoKey)) { // Now see if the command key is down. If it is, get the correct ASCII translation by // masking the command key out and re-translating because the command key will // mask the shift modifier. if (event->IsCommandKeyPressed()) { const short kMaskModifier = 0xFE00; // need to strip command key from Modifiers const long kMaskASCII1 = 0x000000FF; // get key from KeyTranslate return const long kMaskASCII2 = 0x00FF0000; // get key from KeyTranslate return const short kUpKeyMask = 0x0080; int maxCount = event->fDoubleEvent ? 2 : 1; event->fText.Empty(); for (int i = 0; i < maxCount; ++i) { // set the upkey bit so KeyTranslate doesn't do special deadkey processing // See IM-V pp. 195 short keyCodeParameter = ((((event->fEventRecords[i].modifiers) & kMaskModifier) | event->fKeyCode) | kUpKeyMask); // Get the correct keytable pointer. We don't want to grope the system unnecessarily so // use the script managers improvements if they're there. Ptr keyTransTable = (Ptr)(GetScriptManagerVariable(smKCHRCache)); UInt32 state = 0; UInt32 keyInfo = KeyTranslate(keyTransTable, keyCodeParameter, &state); event->fText[i + 1] = (unsigned char)(((keyInfo) & kMaskASCII1)); // Remember fText is a string, the text starts at [1] if (event->fText[i + 1] == 0) event->fText[i + 1] = (unsigned char)((keyInfo & kMaskASCII2) >> 16); } } } } // TDispatcher::KeyEventToComponents //---------------------------------------------------------------------------------------- // TDispatcher::MainEventLoop: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes // must be in the main segment void TDispatcher::MainEventLoop() { fIdlePhase = idleBegin; while (!fDone) this->PollEvent(kAllowApplicationToSleep); } // TDispatcher::MainEventLoop //---------------------------------------------------------------------------------------- // TDispatcher::DoLaunchClipboard: //---------------------------------------------------------------------------------------- #pragma segment MAOpen void TDispatcher::DoLaunchClipboard() { if (gClipboardMgr) { gClipboardMgr->Launch(); // Launch after segments are unloaded // since reading the scrap may be piggy } } // TDispatcher::DoLaunchClipboard //---------------------------------------------------------------------------------------- // TDispatcher::MakeViewForAlienClipboard: //---------------------------------------------------------------------------------------- #pragma segment MAClipboard TView* TDispatcher::MakeViewForAlienClipboard() { return NULL; // use defaults } // TDispatcher::MakeViewForAlienClipboard //---------------------------------------------------------------------------------------- // TDispatcher::DispatchMenuEvent: //---------------------------------------------------------------------------------------- #pragma segment MASelCommand #if qContainer void TDispatcher::DispatchMenuEvent(TToolboxEvent* event, long menuItem) #else void TDispatcher::DispatchMenuEvent(TToolboxEvent* /*event*/, long menuItem) #endif { #if qContainer Boolean proceed = TRUE; if (gContainerLib) proceed = !CADispatchMenuEvent(&event->fEventRecords[0], menuItem); if (event->fDoubleEvent) proceed = !CADispatchMenuEvent(&event->fEventRecords[1], menuItem); if (proceed) #endif this->MenuEvent(menuItem); } //---------------------------------------------------------------------------------------- // TDispatcher::MenuEvent: //---------------------------------------------------------------------------------------- #pragma segment MASelCommand void TDispatcher::MenuEvent(long menuItem) { short theMenuNumber = HiWord(menuItem); short theItemNumber = LoWord(menuItem); if (theMenuNumber) { MAVolatileInit(CommandNumber, command, CommandFromMenuItem(theMenuNumber, theItemNumber)); #if qDebugMsg if (command == cCantUndo) { fprintf(stderr, "Command number %d is reserved for MacApp.\n", cCantUndo); ProgramBreak("Use of reserved command number."); } if (gReportMenuChoices && (command > 0)) fprintf(stderr, "Menu Choice Command Number == %d\n", command); #endif if ((command < 0) && (theMenuNumber == mApple)) { CStr255 deskAccName; GetMenuItemText(MAGetMenuRef(mApple), theItemNumber, deskAccName); this->OpenDeskAccessory(deskAccName); } else if ((command < cEditBase) || (command > cEditLast) || (!SystemEdit((short)(command - cEditBase)))) { FailInfo fi; Try(fi) { if (fSysWindowActive) this->ActivateBusyCursor(TRUE); this->GetTarget()->HandleMenuCommand(command); if (fSysWindowActive) this->ActivateBusyCursor(FALSE); fi.Success(); } else // Recover { if (fSysWindowActive) this->ActivateBusyCursor(FALSE); FailNewMessage(fi.error, fi.message, BuildMessage((short)command, messageCommandError)); } } } } // TDispatcher::MenuEvent //---------------------------------------------------------------------------------------- // TDispatcher::OpenDeskAccessory: //---------------------------------------------------------------------------------------- void TDispatcher::OpenDeskAccessory(const CStr255& deskAccName) { GrafPtr savedPort; GetPort(&savedPort); OpenDeskAcc(deskAccName); SetPort(savedPort); } // TDispatcher::OpenDeskAccessory //---------------------------------------------------------------------------------------- // TDispatcher::ProcessEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::ProcessEvent(TEvent* event) { #if qDebug if (!event) ProgramBreak("NULL passed to TDispatcher::ProcessEvent"); else if (!IsObject(event)) // since it's possible to have passed in a // freed undoable command allocated in a // global variable (due to pilot error) { VerboseIsObject(event); ProgramBreak("bogus object passed to TDispatcher::ProcessEvent"); } else { if (gIntenseDebugging) fprintf(stderr, "The Event to process: %s\n", event->GetClassName()); } #endif if (event) event->Process(); } // TDispatcher::ProcessEvent //---------------------------------------------------------------------------------------- // TDispatcher::PollEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::PollEvent(Boolean allowApplicationToSleep) { MAVolatileInit(Boolean, didAllowApplicationToSleep, fAllowApplicationToSleep); fAllowApplicationToSleep = allowApplicationToSleep; ++fEventLevel; #if qDebugMsg if (!this->GetTarget()) ProgramBreak("Serious Error!! in TDispatcher.PollEvent: target == NULL"); #endif FailInfo fi; Try(fi) { TEvent * retrievedEvent = this->RetrieveAnEvent(); if (retrievedEvent) this->ProcessEvent(retrievedEvent); // The desk scrap may have been changed by use of command-X or command-C in desk accessories. if (fSysWindowActive) { gClipboardMgr->CheckDeskScrap(); this->InvalidateFocus(); } fi.Success(); --fEventLevel; if (fEventLevel == 0) gInhibitNestedHandling = FALSE; // All clear } else // Recover { #if qDebugMsg fprintf(stderr, "\n"); // add a blank line after all the messages from Failure #endif fAllowApplicationToSleep = didAllowApplicationToSleep; --fEventLevel; if (fEventLevel == 0) { if (fi.error != noErr) { #if qSegments UnloadAllSegments(); #endif this->ShowError(fi.error, fi.message); } InvalidateMenus(); } else fi.ReSignal(); } fAllowApplicationToSleep = didAllowApplicationToSleep; } // TDispatcher::PollEvent //---------------------------------------------------------------------------------------- // TDispatcher::PollToolboxEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::PollToolboxEvent(Boolean allowApplicationToSleep) { long waitTicks = 0; RgnHandle sleepRegion = NULL; EventRecord theEvent; if (!::OSEventAvail(fMainEventMask, &theEvent)) // We'll only sleep if there aren't any // waiting Events (keystrokes, mousedowns) { this->SetupTheMenus(); // ensure that a mouse click or key stroke didn't come in during SetupTheMenus if (!::OSEventAvail(fMainEventMask, &theEvent)) { sleepRegion = this->GetSleepRegion(); // ensure that a mouse click or key stroke didn't come in during GetSleepRegion if (!::OSEventAvail(fMainEventMask, &theEvent)) waitTicks = this->GetWaitTicks(allowApplicationToSleep);// calc last so it's most accurate else sleepRegion = NULL; #if qContainer if (gContainerLib) waitTicks = Min(waitTicks, CAGetSleepTime()); #endif } } MAHiliteMenu(0); // Cleanup any menu titles left hilited. // Done here so titles stay hilited until // synchronous actions are performed. TToolboxEvent * event = this->GetEvent(fMainEventMask, waitTicks, sleepRegion); Boolean gotAnEvent = (event != NULL); if (gotAnEvent) { // GetEvent returned an event (work to do). If we were idling before then we must // keep the calls balanced with an IdleEnd to because we are no longer idling if (fIdlePhase == idleContinue) { this->Idle(idleEnd); fIdlePhase = idleBegin; } // Rather than posting the event where it would have to be sorted and compete with // other commands we will process the command directly. this->ProcessEvent(event); // The desk scrap may have been changed by use of command-X or command-C in desk accessories. if (fSysWindowActive) { gClipboardMgr->CheckDeskScrap(); this->InvalidateFocus(); } } else // Woke up with no event available. Truly idle { this->Idle(fIdlePhase); fIdlePhase = idleContinue; } #if qDebug gErrorParm3 = "?????"; // to prevent anyone from using old values #endif return gotAnEvent; } // TDispatcher::PollToolboxEvent //---------------------------------------------------------------------------------------- // TDispatcher::PostAnEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::PostAnEvent(TEvent* event) // Override { FailInfo fi; Try(fi) { if (event->IsReadyToPost()) fEventList->Insert(event); // inserts event ordered the list fi.Success(); } else { if (event->ShouldFreeOnCompletion()) event = (TEvent *)FreeIfObject(event); fi.ReSignal(); } } // TDispatcher::PostAnEvent //---------------------------------------------------------------------------------------- // TDispatcher::PostCommand: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::PostCommand(TCommand* command)// Override { if (command) { if (command->CanBeUndone()) TUndoHandler::fgUndoHandler->AddActionToHistory(command, kSingleAction, command->fIdentifier); this->PostAnEvent(command); } } // TDispatcher::PostCommand //---------------------------------------------------------------------------------------- // TDispatcher::DidEvent: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DidEvent(TToolboxEvent* event) { if (event && event->fAffectsMenus) InvalidateMenus(); Boolean perm = PermAllocation(FALSE); #if qDebug if (perm) ProgramBreak("The permanent flag was left true."); #endif if (event && (event->ShouldFreeOnCompletion())) event = (TToolboxEvent *)FreeIfObject(event); } // TDispatcher::DidEvent //---------------------------------------------------------------------------------------- // TDispatcher::RegainControl: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::RegainControl(Boolean checkClipboard) { #if qNeedsVU gClipboardMgr->RegainControl(checkClipboard); #endif this->Changed(mRegainControl, this); this->ActivateBusyCursor(TRUE); gClipboardMgr->RegainControl(checkClipboard); // Let all windows know that we're regaining control - e.g. so floaters can show themselves CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if (aWindow) aWindow->RegainControl(); } CDocumentIterator docIter(this); for (TDocument * aDocument = docIter.FirstDocument(); docIter.More(); aDocument = docIter.NextDocument()) aDocument->RegainControl(); } // TDispatcher::RegainControl //---------------------------------------------------------------------------------------- // TDispatcher::Run: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes // must be in the main segment void TDispatcher::Run() { #if qSegments UnloadAllSegments(); #endif FailSpaceIsLow(); // make sure we have enough memory to continue gInitialized = TRUE; // was set false at static init time this->DoLaunchClipboard(); #if qSegments UnloadAllSegments(); #endif if (fWantKeyUpEvents) ::SetEventMask(everyEvent); // allow us to get keyup events too. fEventLevel = 0; // Indicate outermost level this->MainEventLoop(); // runs until a quit command this->AboutToLoseControl(TRUE); // See if previous max. resource usage has been exceeded by the termination code and // resources. CheckRsrcUsage(); if (TPrintHandler::gPrintHandler) // shut down the printing system TPrintHandler::gPrintHandler->TerminateUPrinting(); TView::TerminateUView(); // shut down the view system // We must call CleanupMacApp here; if we wait to fall thru to the end of the main // program, A5 has been invalidated and we can't refer to any globals. CleanupMacApp(); } // TDispatcher::Run //---------------------------------------------------------------------------------------- // TDispatcher::GetMainEventMask: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes short TDispatcher::GetMainEventMask() { return fMainEventMask; } //---------------------------------------------------------------------------------------- // TDispatcher::SetMainEventMask: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes short TDispatcher::SetMainEventMask(short newMask) { short oldMask = fMainEventMask; fMainEventMask = newMask; return oldMask; } //---------------------------------------------------------------------------------------- // TDispatcher::SetTarget: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::SetTarget(TEventHandler* newTarget) { if (newTarget == NULL) { newTarget = this; #if qDebug ProgramBreak("In TDispatcher.SetTarget… you're setting the global target to NULL!"); #endif } if (newTarget != fTarget) { fTarget->ResignedTarget(); fTarget = newTarget; fTarget->BecameTarget(); this->InvalidateMouseRegions(); } } // TDispatcher::SetTarget //---------------------------------------------------------------------------------------- // TDispatcher::SetupUndoRedoMenus: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::SetupUndoRedoMenus() { if (TUndoHandler::fgUndoHandler->AnythingToUndo()) Enable(cUndo, TRUE); SetUndoText(TUndoHandler::fgUndoHandler->GetUndoID()); if (TUndoHandler::fgUndoHandler->AnythingToRedo()) Enable(cRedo, TRUE); SetRedoText(TUndoHandler::fgUndoHandler->GetRedoID()); } //---------------------------------------------------------------------------------------- // TDispatcher::SetUndoText: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::SetUndoText(CommandNumber id) { if (fUndoCommand != id) { CStr255 undoName; GetUndoRedoText(kShowUndo, id, undoName); SetCommandName(cUndo, undoName); fUndoCommand = id; } } //---------------------------------------------------------------------------------------- // TDispatcher::SetRedoText: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::SetRedoText(CommandNumber id) { if (fRedoCommand != id) { CStr255 redoName; GetUndoRedoText(kShowRedo, id, redoName); SetCommandName(cRedo, redoName); fRedoCommand = id; } } //---------------------------------------------------------------------------------------- // TDispatcher::SetupTheMenus: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::SetupTheMenus() { #if qContainer if(!gHasODFocus) return; //if we don't have the focus, we should not be messing with the menus. else { #endif if (this->IsFrontProcess() && (MenusHavePendingUpdate())) { gMenuBarManager->Reset(); // reset the preferred menubar PerformMenuSetup(&DoSetupTheMenus, NULL); gMenuBarManager->InstallPreferredMenus(); if (MenusHavePendingUpdate()) { // Add the debugger menu #if qDebug || qPerform AddMenuBar(kMBarDebug, FALSE); #endif // Recurse to get the menus correctly setup this->SetupTheMenus(); } } #if qContainer } #endif } // TDispatcher::SetupTheMenus //---------------------------------------------------------------------------------------- // TDispatcher::ShowError: //---------------------------------------------------------------------------------------- #pragma segment MAError void TDispatcher::ShowError(OSErr error, long message) { ErrorAlert(error, message); } // TDispatcher::ShowError //---------------------------------------------------------------------------------------- // TDispatcher::SpaceIsLowAlert: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::SpaceIsLowAlert() { // Show 'space is low' alert only after ever fLowSpaceInterval ticks. if ((fLowSpaceInterval > 0) && this->IsFrontProcess()) { if (TickCount() > fNextSpaceMessage) { gInhibitNestedHandling = TRUE; // Don't tell em again from the alert StdAlert(phSpaceIsLow); fNextSpaceMessage = TickCount() + fLowSpaceInterval; } } } // TDispatcher::SpaceIsLowAlert //---------------------------------------------------------------------------------------- // TDispatcher::DoSetCursor: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DoSetCursor(CPoint globalMouse, RgnHandle cursorRegion) { this->GetDefaultCursorRegion(globalMouse, cursorRegion); SetCursor(&(qd.arrow)); } // TDispatcher::DoSetCursor //---------------------------------------------------------------------------------------- // TDispatcher::HandleCursor: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleCursor(CPoint globalMouse, RgnHandle cursorRegion) { WindowRef aWMgrWindow; if (FindWindow(globalMouse, &aWMgrWindow) == inContent) { TWindow * cursorWindow = this->WMgrToWindow(aWMgrWindow); if (cursorWindow) { if (gDispatcher->GetFrontWindow() == cursorWindow || !gDispatcher->InModalState()) { if (cursorWindow->HandlesCursor()) { VPoint windowVPt(globalMouse); cursorWindow->SuperToLocal(windowVPt); cursorWindow->HandleCursor(windowVPt, cursorRegion); // Convert cursor region from window coords to global coords cursorWindow->LocalToSuperRegion(cursorRegion); } #if qDrag else if (HasDragManager()) { VPoint windowVPt(globalMouse); cursorWindow->SuperToLocal(windowVPt); cursorWindow->HandleDragCursor(windowVPt, cursorRegion); cursorWindow->LocalToSuperRegion(cursorRegion); } #endif cursorWindow->Focus(); // leave the window origin and clip set // so that external utilities such as // English Speech Recognition will find // controls unclipped. } } } } // TDispatcher::HandleCursor //---------------------------------------------------------------------------------------- // TDispatcher::TrackCursor: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::TrackCursor(CPoint globalMouse) { FailInfo fi; Try(fi) { #if qDebugMsg if (PtInRgn(globalMouse, fCursorRegion)) { if (gIntenseDebugging) fprintf(stderr, "cursor is in cursor region\n"); } #endif this->InvalidateCursorRgn(); // Find out if the cursor is in a window which handles the cursor, and if so, call // HandleCursor to allow a view to claim the cursor, and compute a region this->HandleCursor(*((CPoint *)&globalMouse), fCursorRegion); if (EmptyRgn(fCursorRegion)) this->DoSetCursor(globalMouse, fCursorRegion); // Make sure the cursorpoint is included TView::PtAndRgn(globalMouse, fCursorRegion); #if qDebugMsg if (gIntenseDebugging) if (fCursorRegion == NULL) fprintf(stderr, "fCursorRegion is NULL\n"); #endif #if qDebug if (gIntenseDebugging && !PtInRgn(globalMouse, fCursorRegion)) { CRect bBox = (*fCursorRegion)->rgnBBox; fprintf(stderr, "Whoops, cursor region was not correctly calculated.\n"); fprintf(stderr, "global cursor = ", (const char*)globalMouse); fprintf(stderr, " (*fCursorRegion)->rgnBBox = ", (const char*) bBox); fprintf(stderr, "\n"); ProgramBreak("The cursor is not in the cursor region at end of TDispatcher.TrackCursor!"); } #endif fi.Success(); } else // Recover { #if qDebugMsg fprintf(stderr, "TrackCursor failed\n"); #endif SetEmptyRgn(fCursorRegion); // don't ReSignal } } // TDispatcher::TrackCursor //---------------------------------------------------------------------------------------- // TDispatcher::DoShowHelp: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::DoShowHelp(CPoint globalMouse, RgnHandle helpRegion) { if (HMIsBalloon()) { OSErr err = HMRemoveBalloon(); if (err != hmNoBalloonUp) FailOSErr(err); } this->GetDefaultHelpRegion(globalMouse, helpRegion); } // TDispatcher::DoShowHelp //---------------------------------------------------------------------------------------- // TDispatcher::HandleHelp: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::HandleHelp(CPoint globalMouse, RgnHandle helpRegion) { WindowRef aWMgrWindow; if (FindWindow(globalMouse, &aWMgrWindow) == inContent) { TWindow * helpWindow = this->WMgrToWindow(aWMgrWindow); if ((helpWindow) && helpWindow->HandlesHelp()) { VPoint windowVPt(*((CPoint *)&globalMouse)); helpWindow->SuperToLocal(windowVPt); helpWindow->HandleHelp(windowVPt, helpRegion); // Convert helpRegion region from window coords to global coords helpWindow->LocalToSuperRegion(helpRegion); } } } // TDispatcher::HandleHelp //---------------------------------------------------------------------------------------- // TDispatcher::TrackHelp: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::TrackHelp(CPoint globalMouse) { #if qDebugMsg if (PtInRgn(globalMouse, fHelpRegion)) { if (gIntenseDebugging) fprintf(stderr, "cursor is in help region\n"); } #endif this->InvalidateHelpRgn(); // Find out if the cursor is in a window which handles help, and if so, call // HandleHelp to allow some subview to show help, and compute a region this->HandleHelp(*((CPoint *)&globalMouse), fHelpRegion); if (EmptyRgn(fHelpRegion)) this->DoShowHelp(globalMouse, fHelpRegion); // Make sure the cursorpoint is included TView::PtAndRgn(globalMouse, fHelpRegion); #if qDebugMsg if (gIntenseDebugging) if (fHelpRegion == NULL) fprintf(stderr, "fHelpRegion is NULL\n"); #endif #if qDebug if (gIntenseDebugging && !PtInRgn(globalMouse, fHelpRegion)) { CRect bBox = (*fHelpRegion)->rgnBBox; fprintf(stderr, "Whoops, help region was not correctly calculated.\n"); fprintf(stderr, "global cursor = ", (const char*)globalMouse); fprintf(stderr, " (*fHelpRegion)->rgnBBox = ", (const char*) bBox); fprintf(stderr, "\n"); ProgramBreak("The cursor is not in the help region at end of TDispatcher.TrackHelp!"); } #endif } // TDispatcher::TrackHelp //---------------------------------------------------------------------------------------- // TDispatcher::TrackMouse: //---------------------------------------------------------------------------------------- #pragma segment MADoCommand TTracker* TDispatcher::TrackMouse(const VPoint& theMouse, CPoint hysteresis, TTracker* theCommand) { MAVolatileInit(TTracker*, currentTracker, NULL); // so failure handler works MAVolatileInit(TTracker*, volatileCommand, theCommand); // so failure handler works FailInfo fi; Try(fi) { currentTracker = volatileCommand->HandleTrackBegin(theMouse, hysteresis); volatileCommand = NULL; // so failure handler works while (currentTracker && !currentTracker->IsDoneTracking()) if (this->IsFrontProcess()) currentTracker = currentTracker->HandleTrackContinue(); if (currentTracker) currentTracker = currentTracker->HandleTrackEnd(); fi.Success(); } else // Recover { if (volatileCommand) { volatileCommand->Completed(); if (volatileCommand->ShouldFreeOnCompletion()) volatileCommand = (TTracker*) FreeIfObject(volatileCommand); } if (currentTracker) { currentTracker->Completed(); if (currentTracker->ShouldFreeOnCompletion()) currentTracker = (TTracker*) FreeIfObject(currentTracker); } fi.ReSignal(); } return currentTracker; } // TDispatcher::TrackMouse //---------------------------------------------------------------------------------------- // TDispatcher::UpdateAllWindows: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::UpdateAllWindows() { TToolboxEvent * event; ++fEventLevel; // Something bad could happen here if for some reason the event queue was blocked (constipated?) // or something, causing us to loop forever. Let's put an unreasonable upper bound on the number // of events we'll handle in this loop. int maxEvents = 500; while ((event = this->GetEvent(updateMask | activMask, 0, NULL)) != NULL && maxEvents--) event->Process(); --fEventLevel; } // TDispatcher::UpdateAllWindows //---------------------------------------------------------------------------------------- // TDispatcher::DoMakeViewServer: //---------------------------------------------------------------------------------------- #pragma segment MAInit void TDispatcher::DoMakeViewServer() { TViewServer * aViewServer = new TViewServer; aViewServer->IViewServer(); // assigns the global reference } // TDispatcher::DoMakeViewServer //---------------------------------------------------------------------------------------- // TDispatcher::WMgrToWindow: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes TWindow* TDispatcher::WMgrToWindow(WindowRef aWindowPtr) { // just uses the global routine in UWindow return TWindow::WMgrToWindow(aWindowPtr); } // TDispatcher::WMgrToWindow //---------------------------------------------------------------------------------------- // TDispatcher::GetApplicationName: //---------------------------------------------------------------------------------------- #pragma segment MAWriteFile void TDispatcher::GetApplicationName(CStr255& theName) { FailInfo fi; Try(fi) { ProcessInfoRec info; info.processInfoLength = sizeof(ProcessInfoRec); info.processName = theName; info.processAppSpec = NULL; FailOSErr(GetProcessInformation(&fProcessNumber, &info)); fi.Success(); } else { #if qDebug ProgramBreak("TDispatcher::GetApplicationName() failed!"); #endif // no need to fail completely, just return generic string theName = "<Application>"; // Don't ReSignal } } // TDispatcher::GetApplicationName //---------------------------------------------------------------------------------------- // TDispatcher::DoUndoRedo: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes Boolean TDispatcher::DoUndoRedo(TCommandHandler* theContext, CommandNumber aCommandNumber, MScriptableObject* theTarget) // Handles the undo choice from the menu. If you want undo/redo to be recordable // your DoMenuCommand method should call this on cUndo. { TCommand * lastCommand = theContext->GetLastCommand(); if (lastCommand && (lastCommand->fContext == theContext)) { DescType theEventType; if (lastCommand->fCommandDone) theEventType = kAEUndo; else theEventType = kAERedo; TAppleEvent * theEvent = new TAppleEvent; theEvent->IAppleEvent(kAEMiscStandards, theEventType, gServerAddress, kAEWaitReply); CTempDesc targetDesc; theTarget->MakeObjectSpecifier(targetDesc, theTarget->GetSpecifierForm()); theEvent->WriteParameter(keyDirectObject, targetDesc); TClientCommand * theCmd = new TClientCommand; theCmd->IClientCommand(aCommandNumber, theContext, FALSE, FALSE, theContext, theEvent); this->PostCommand(theCmd); return TRUE; } else return FALSE; } //---------------------------------------------------------------------------------------- // TDispatcher::UndoRedoInContext: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes Boolean TDispatcher::UndoRedoInContext(TCommandHandler* /*theContext*/, CommandNumber aCommandNumber) // Handles the undo event. TDispatcher will handle this for itself, but if // you handle undo/redo in another context you should call this from that object's // DoScriptCommand method. { Boolean completed = FALSE; if (aCommandNumber == cAEUndo || aCommandNumber == cAERedo) { Boolean oldTempAlloc = TemporaryAllocation(TRUE); Boolean oldObjectPerm = AllocateObjectsFromPerm(FALSE); // Generate the proper undo or redo command. if (aCommandNumber == cAEUndo) { TUndoCommand* anUndoOrRedoCommand = NULL; anUndoOrRedoCommand = new TUndoCommand(); anUndoOrRedoCommand->IUndoCommand(aCommandNumber); anUndoOrRedoCommand->Process(); } else { TRedoCommand* anUndoOrRedoCommand = NULL; anUndoOrRedoCommand = new TRedoCommand(); anUndoOrRedoCommand->IRedoCommand(aCommandNumber); anUndoOrRedoCommand->Process(); } TemporaryAllocation(oldTempAlloc); AllocateObjectsFromPerm(oldObjectPerm); completed = TRUE; } return completed; } //---------------------------------------------------------------------------------------- // TDispatcher::CountContainedObjects: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes long TDispatcher::CountContainedObjects(DescType desiredType) { // Counts the number of windows or documents the application has open. long result = 0; switch (desiredType) { case cMenu: { result = CountMenus(gMenuBarManager->fDisplayedMenus); } break; case cPalette: case cWindow: { // Go through the window list and count the visible windows. CWMgrIterator iter; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); iter.More(); aWinPtr = iter.NextWMgrWindow()) { TWindow * aWindow = this->WMgrToWindow(aWinPtr); if ((aWindow) && aWindow->IsShown() && (aWindow->GetOMClass() == desiredType)) result++; } } break; default: { // Go through the document list and count the documents of this type. CNoGhostDocsIterator iter(this); for (TDocument * aDocument = iter.FirstDocument(); iter.More(); aDocument = iter.NextDocument()) if ((aDocument->GetOMClass() == desiredType) || (desiredType == cDocument)) result++; } break; } return result; } #if qAttachable //---------------------------------------------------------------------------------------- // TDispatcher::HandleOSAEvent: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes Boolean TDispatcher::HandleOSAEvent(CommandNumber aCommandNumber, TAppleEvent* message, TAppleEvent* reply) { // Don't give OSA the run event so that scripts won't have to continue it. return (aCommandNumber != cFinderNew) && MScriptableObject::HandleOSAEvent(aCommandNumber, message, reply); } #endif // qAttachable //---------------------------------------------------------------------------------------- // TDispatcher::DoScriptCommand: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes void TDispatcher::DoScriptCommand(CommandNumber aCommandNumber, TAppleEvent* message, TAppleEvent* reply) { TEventHandler * theTarget = this->GetTarget(); switch (aCommandNumber) { case cAEUndo: case cAERedo: if (CommandEnabled(cUndo)) this->UndoRedoInContext(this, aCommandNumber); break; case cAEPaste: if (CommandEnabled(cPaste)) theTarget->HandleMenuCommand(cPaste); break; case cAECut: if (CommandEnabled(cCut)) theTarget->HandleMenuCommand(cCut); break; case cAECopy: if (CommandEnabled(cCopy)) theTarget->HandleMenuCommand(cCopy); break; default: MDefaultScriptableObject::DoScriptCommand(aCommandNumber, message, reply); break; } } //---------------------------------------------------------------------------------------- // TDispatcher::SetObjectProperty: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes void TDispatcher::SetObjectProperty(const CAEDesc& thePropertyValue, DescType whichProperty) { CAEDesc localPropValue = thePropertyValue; switch (whichProperty) { case pClipboard: { gClipboardMgr->AboutToLoseControl(TRUE);// so scrap gets converted FailOSErr((short)ZeroScrap()); if (localPropValue.GetDescriptorType() == typeAEList) { // Put all the elements of the list on the scrap long count = 0; FailOSErr(AECountItems(localPropValue, &count)); while (count) { CTempDesc theScrapData; DescType theAEKeyword; FailOSErr(AEGetNthDesc(localPropValue, count--, typeWildCard, &theAEKeyword, theScrapData)); gClipboardMgr->PutDeskScrapData(theScrapData.GetDescriptorType(), theScrapData.GetDataHandle()); } } else { gClipboardMgr->PutDeskScrapData(localPropValue.GetDescriptorType(), localPropValue.GetDataHandle()); } gClipboardMgr->RegainControl(TRUE);// so scrap gets converted } break; case pName: case pIsFrontProcess: case pVersion: case pUserSelection: FailOSErr(errAECantSetReadOnly); break; default: MScriptableObject::SetObjectProperty(thePropertyValue, whichProperty); break; } } //---------------------------------------------------------------------------------------- // TDispatcher::GetObjectProperty: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes Boolean TDispatcher::GetObjectProperty(CAEDesc& thePropertyValue, DescType whichProperty, const CAEDesc& desiredType) { // Return properties for the application. Boolean hasProperty = TRUE; FailInfo fi; Try(fi) { switch (whichProperty) { case pClipboard: { // Since we don't know what's on the scrap and we're trying to return // its contents in a generic way, we'll get the desk scrap handle // and walk down it grabbing each scrap type we come upon. Boolean inFront = this->IsFrontProcess(); if (inFront) { gClipboardMgr->AboutToLoseControl(TRUE);// so scrap gets converted gClipboardMgr->RegainControl(TRUE);// so scrap gets converted } FailOSErr((short)LoadScrap()); PScrapStuff pScrpInf = InfoScrap(); Handle theScrap = pScrpInf->scrapHandle; MAVolatileInit(THandleStream*, theScrapStream, NULL); MAVolatileInit(Handle, theScrapData, NULL); FailInfo scrapFail; Try(scrapFail) { theScrapStream = new THandleStream; theScrapData = NewPermHandle(0); theScrapStream->IHandleStream(theScrap, 0); thePropertyValue.CreateList(); while ((theScrapStream->GetPosition() + 8) < pScrpInf->scrapSize) { DescType theScrapType = (DescType)theScrapStream->ReadLong(); long theLength = theScrapStream->ReadLong(); SetPermHandleSize(theScrapData, theLength); FailMemError(); SignedByte wasState = LockHandle(theScrapData); theScrapStream->ReadBytes(*theScrapData, theLength); HSetState(theScrapData, wasState); CAEDesc theScrapDesc(theScrapType, theScrapData); FailOSErr(AEPutDesc(thePropertyValue, 0, theScrapDesc)); } theScrapData = DisposeIfHandle(theScrapData); theScrapStream = (THandleStream *)FreeIfObject(theScrapStream); scrapFail.Success(); } else { theScrapData = DisposeIfHandle(theScrapData); theScrapStream = (THandleStream *)FreeIfObject(theScrapStream); scrapFail.ReSignal(); } } break; case pName: { CStr255 theAppName; GetApplicationName(theAppName); thePropertyValue.PutString(theAppName); } break; case pIsFrontProcess: thePropertyValue.PutBoolean(this->IsFrontProcess()); break; case pVersion: { short refNum = MACurResFile(); // save current resource Handle theVersResource = NULL; FailResError(); FailInfo versionFail; Try(versionFail) { CAEDesc propData; MAUseResFile(gApplicationRefNum);// set this resource to be current theVersResource = (Handle)Get1Resource((ResType)'vers', 1); SignedByte wasState = LockHandle(theVersResource); FailOSErr(AECreateDesc(typeVersion, *theVersResource, GetHandleSize(theVersResource), propData)); thePropertyValue = propData; HSetState(theVersResource, wasState); ReleaseResource(theVersResource); MAUseResFile(refNum); // reset back to resource previously set versionFail.Success(); } else { HUnlock(theVersResource); ReleaseResource(theVersResource); MAUseResFile(refNum); // reset back to resource previously set versionFail.ReSignal(); } } break; case pUserSelection: { TWindow * theFrontWindow = this->GetFrontWindow(); if (theFrontWindow) { TDocument * theDoc = theFrontWindow->fDocument; if (theDoc) { TDesignator *theUserSelection = theDoc->GetUserSelection(); FailNonObject(theUserSelection); CAEDesc propData; theUserSelection->MakeObjectSpecifier(propData, formPropertyID); thePropertyValue = propData; } } } break; default: hasProperty = MScriptableObject::GetObjectProperty(thePropertyValue, whichProperty, desiredType); break; } fi.Success(); } else { // we failed while trying to get the property hasProperty = FALSE; // Don't ReSignal } return hasProperty; } //---------------------------------------------------------------------------------------- // TDispatcher::MakeObjectSpecifier: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes Boolean TDispatcher::MakeObjectSpecifier(CAEDesc& theObjectSpecifier, DescType /*preferredForm*/) { //return (AECreateDesc(typeNull, NULL, 0, theObjectSpecifier) == noErr); FailOSErr(AECreateDesc(typeNull, NULL, 0, theObjectSpecifier)); return TRUE; } //---------------------------------------------------------------------------------------- // TDispatcher::GetContainedObject: //---------------------------------------------------------------------------------------- #pragma segment OSLDispatchRes MScriptableObject* TDispatcher::GetContainedObject(DescType desiredType, DescType selectionForm, const CAEDesc& selectionData) { MScriptableObject * result = NULL; if (desiredType == cFile) { // When you script 'file "Macintosh HD:My File"' AppleScript will // give the app a pathname and expect a file object in return. TFile * resultFile = this->DoMakeFile(cOpen); CStr255 thePathName; selectionData.GetString(thePathName); resultFile->SpecifyWithTrio(0, 0, (CStr63 &)thePathName); TOSADispatcher::fgDispatcher->AddTemporaryToken(resultFile); result = resultFile; } else if (desiredType == cDocument && selectionForm == formName) { // We know we're going after a document with a // specific name so just scan the document list. CStr255 theDocName; CNoGhostDocsIterator iter(this); TDocument* aDocument = iter.FirstDocument(); selectionData.GetString(theDocName); do { if ((aDocument->GetOMClass() == desiredType) && (aDocument->fTitle == theDocName)) // Should this be IUEqualString? result = aDocument; aDocument = iter.NextDocument(); } while (result == NULL && iter.More()); } else result = MScriptableObject::GetContainedObject(desiredType, selectionForm, selectionData); return result; } //---------------------------------------------------------------------------------------- // TDispatcher::GetIndContainedObject: //---------------------------------------------------------------------------------------- #pragma segment OSLDispatchRes MScriptableObject* TDispatcher::GetIndContainedObject(DescType desiredType, long index) { MScriptableObject *indexedObject; switch(desiredType) { case cWindow: indexedObject = GetWindowByIndex((short)index); break; case cPalette: indexedObject = GetPaletteByIndex((short)index); break; case cMenu: { // Create a menu accessor to handle events for this menu MenuRef theMenuRef = GetIndMenu(gMenuBarManager->fDisplayedMenus, (short)index); if (theMenuRef == NULL) return NULL; // no such menu TMenuAccessor* theAccessor = new TMenuAccessor; theAccessor->IMenuAccessor(theMenuRef, (short)index); TOSADispatcher::fgDispatcher->AddTemporaryToken(theAccessor); indexedObject = theAccessor; } break; default: if (IsDocumentClass(desiredType)) indexedObject = GetDocumentByIndex(desiredType, (short)index); else indexedObject = MScriptableObject::GetIndContainedObject(desiredType, index); break; } return indexedObject; } //---------------------------------------------------------------------------------------- // TDispatcher::GetWindowByIndex: //---------------------------------------------------------------------------------------- #pragma segment OSLDispatchRes TWindow* TDispatcher::GetWindowByIndex(short wIndex) { CWMgrIterator iter; short windowCount = 0; TWindow *indexedWindow = NULL; TWindow *tempWindow; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); (windowCount < wIndex) && iter.More(); aWinPtr = iter.NextWMgrWindow()) { if (!TWindow::IsFloatWindow(aWinPtr)) { tempWindow = this->WMgrToWindow(aWinPtr); if (tempWindow && tempWindow->IsShown()) { windowCount++; if (windowCount == wIndex) indexedWindow = tempWindow; } } } return indexedWindow; } //---------------------------------------------------------------------------------------- // TDispatcher::GetPaletteByIndex: //---------------------------------------------------------------------------------------- #pragma segment OSLDispatchRes TWindow* TDispatcher::GetPaletteByIndex(short index) { CWMgrIterator iter; short paletteCount = 0; TWindow *indexedPalette = NULL; TWindow *tempWindow; for (WindowRef aWinPtr = iter.FirstWMgrWindow(); (paletteCount < index) && iter.More(); aWinPtr = iter.NextWMgrWindow()) { if (TWindow::IsFloatWindow(aWinPtr)) { tempWindow = this->WMgrToWindow(aWinPtr); if (tempWindow && tempWindow->IsShown()) { paletteCount++; if (paletteCount == index) indexedPalette = tempWindow; } } } return indexedPalette; } //---------------------------------------------------------------------------------------- // TDispatcher::GetDocumentByIndex: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes TDocument* TDispatcher::GetDocumentByIndex(DescType desiredType, short wIndex) { // Go through the window list and count to the Nth window associated with a document // of the desired type. Only count the first window for each document just // in case a document has more than one window. TWindow* aWindow = NULL; TWindow* theFrontWindow = GetFrontWindow(); TDocument* aDocument = NULL; if (theFrontWindow) { // Make a list for all of the documents we find until we find the one we want. TDynamicArray* aDocList = new TDynamicArray; aDocList->IDynamicArray(20, sizeof(TDocument*)); WindowRef theWindowPtr = theFrontWindow->fWMgrWindow; short index = 0; while ((theWindowPtr != NULL) && (index < wIndex)) { aWindow = this->WMgrToWindow(theWindowPtr); if (aWindow) { aDocument = aWindow->fDocument; if (aDocument && (aDocument->GetOMClass() == desiredType)) { // See if this document is already in the list. CArrayIterator iter(aDocList); Boolean found = FALSE; for (ArrayIndex i = iter.FirstIndex(); iter.More() && !found; i = iter.NextIndex()) found = (aDocument == (TDocument*)((*aDocList)[i])); if (!found) { index++; aDocList->InsertElementsBefore(aDocList->GetSize() + 1, &aDocument, 1); } } } theWindowPtr = GetNextWindow(theWindowPtr); } aDocList->Free(); } return aDocument; } //---------------------------------------------------------------------------------------- // TDispatcher::IsDocumentClass: //---------------------------------------------------------------------------------------- #pragma segment OSLDispatchRes Boolean TDispatcher::IsDocumentClass(DescType desiredType) { return desiredType == cDocument; } //---------------------------------------------------------------------------------------- // TDispatcher::ReportReplyError: //---------------------------------------------------------------------------------------- #pragma segment MAScriptingRes void TDispatcher::ReportReplyError(CommandNumber/*fromCmdNum*/ , OSErr theError, const CStr255& theErrStr) { // When a TClientCommand gets an error back from an AppleEvent it calls this // method so the application can report the error on the client side. if (theErrStr.Length()) { ParamText(theErrStr, gEmptyString, gEmptyString, gEmptyString); StdAlert(phUnknownErr); ResetAlertStage(); } else if (theError != noErr) ErrorAlert(theError, 0); } #if qContainer //------------------------------------------------------------------------------------ // Container Application Support //------------------------------------------------------------------------------------ // The following five functions are static. The must be resident! // Huh? They just need to be in the jump table. //---------------------------------------------------------------------------------------- // TDispatcher::FocusAcquiredProc: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::FocusAcquiredProc(CADocumentRef aCADocRef, CAFocusType focusType) { // Save current port. i.e. GetPort (&savePort); // Focus on the documents window. switch (focusType) { case kCAPrimaryFocus: gHasODFocus = TRUE; // Save the focus document gDispatcher->fCurrentDocument = aCADocRef; // Set and draw the app menu bar if (gMenuBarManager->fAppMenuBar) { ::SetMenuBar(gMenuBarManager->fAppMenuBar); ::DrawMenuBar(); //MacApp thinks the menus have not changed } // Invalidate selection regions break; case kCAModalFocus: gHasODModalFocus = TRUE; break; default: break; } // Refocus on the original port. i.e. SetPort (savePort); } //---------------------------------------------------------------------------------------- // TDispatcher::FocusLostProc: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::FocusLostProc(CADocumentRef aCADocRef, CAFocusType focusType) { // Save current port. i.e. GetPort (&savePort); // Focus on the documents window. switch (focusType) { case kCAPrimaryFocus: gHasODFocus = FALSE; // We no longer have the currently focused document. gDispatcher->fCurrentDocument = NULL; // Invalidate the selection indicators. break; case kCAModalFocus: gHasODModalFocus = FALSE; break; default: break; } // Refocus on the original port. i.e. SetPort (savePort); } //---------------------------------------------------------------------------------------- // TDispatcher::WindowActivateHandler: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes void TDispatcher::WindowActivateHandler(WindowPtr theWindow, Boolean activating) { //TWindow * aWindow = gDispatcher->WMgrToWindow((WindowRef)(event->fEventRecord.message)); TWindow * aWindow = gDispatcher->WMgrToWindow((WindowRef)FrontWindow()); if (aWindow) { if (aWindow->fFloats) // ignore floaters { TWindow* frontWindow = gDispatcher->GetFrontWindow(); // find frontmost non-floating window if (frontWindow) { aWindow = frontWindow; // (de)activate it instead of the floater HiliteWindow(aWindow->fWMgrWindow, activating); } } aWindow->Activate(activating); } } //---------------------------------------------------------------------------------------- // TDispatcher::FrameShapeRequestHandler: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes pascal Boolean TDispatcher::FrameShapeRequestHandler(CADocumentRef aCADocRef, CAFrameRef frameRef, RgnHandle aRgn) { // Iterate over the embedded frames of a document (Document has list?) // Find frame that it wants via frameRef // Ask the corresponding view if it will change. Boolean grantedRequest = FALSE; CCADocumentIterator iter(gDispatcher); for (TFileBasedDocument * aCADocument = iter.FirstDocument(); iter.More(); aCADocument = iter.NextDocument()) { if(aCADocument->GetContainer() == aCADocRef) { CODPartViewIterator viewIter(aCADocument); for (TODPartView * anODView = viewIter.FirstODPartView(); viewIter.More(); anODView = viewIter.NextODPartView()) if (anODView->GetFrameRef() == frameRef) grantedRequest = anODView->NegotiateFrameChange(aRgn); } } return grantedRequest; } //---------------------------------------------------------------------------------------- // TDispatcher::AdjustBorderHandler: //---------------------------------------------------------------------------------------- #pragma segment MAApplicationRes Boolean TDispatcher::AdjustBorderHandler(CADocumentRef aCADocRef, CAFrameRef frameRef, RgnHandle aRgn) { return FALSE; } #endif // qContainer //---------------------------------------------------------------------------------------- // End of UDispatcher.cp #pragma segment Inline